2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * Copyright (C) 2017 Amdocs
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
20 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 package org.openecomp.appc.adapter.chef.impl;
26 import java.util.ArrayList;
27 import java.util.HashMap;
28 import java.util.List;
30 import java.util.Properties;
32 import java.util.regex.Pattern;
34 import org.glassfish.grizzly.http.util.HttpStatus;
35 import org.openecomp.appc.Constants;
36 import org.openecomp.appc.adapter.chef.ChefAdapter;
37 import org.openecomp.appc.adapter.chef.chefapi.*;
38 import org.openecomp.appc.adapter.chef.chefclient.*;
39 import org.openecomp.appc.configuration.Configuration;
40 import org.openecomp.appc.configuration.ConfigurationFactory;
41 import org.openecomp.appc.exceptions.APPCException;
42 import org.openecomp.appc.exceptions.UnknownProviderException;
43 import org.openecomp.appc.i18n.Msg;
44 import org.openecomp.appc.pool.Pool;
45 import org.openecomp.appc.pool.PoolExtensionException;
46 import org.openecomp.appc.util.StructuredPropertyHelper;
47 import org.openecomp.appc.util.StructuredPropertyHelper.Node;
48 import com.att.cdp.exceptions.ContextConnectionException;
49 import com.att.cdp.exceptions.ResourceNotFoundException;
50 import com.att.cdp.exceptions.TimeoutException;
51 import com.att.cdp.exceptions.ZoneException;
52 import com.att.cdp.pal.util.StringHelper;
53 import com.att.cdp.zones.ComputeService;
54 import com.att.cdp.zones.Context;
55 import com.att.cdp.zones.ImageService;
56 import com.att.cdp.zones.Provider;
57 import com.att.cdp.zones.model.Image;
58 import com.att.cdp.zones.model.Server;
59 import com.att.cdp.zones.model.ServerBootSource;
60 import com.att.cdp.zones.model.Server.Status;
61 import com.att.eelf.configuration.EELFLogger;
62 import com.att.eelf.configuration.EELFManager;
63 import com.att.eelf.i18n.EELFResourceManager;
64 import org.openecomp.sdnc.sli.SvcLogicContext;
67 import java.net.InetAddress;
68 import java.util.Locale;
69 import java.util.UUID;
71 import org.apache.http.*;
72 import org.apache.http.client.*;
73 import org.apache.http.client.methods.*;
74 import org.apache.http.impl.client.*;
75 import org.apache.http.util.EntityUtils;
77 import static com.att.eelf.configuration.Configuration.*;
79 import java.io.IOException;
81 import java.net.InetAddress;
83 import java.io.BufferedInputStream;
85 import java.io.FileInputStream;
86 import java.io.FileOutputStream;
87 import java.io.IOException;
88 import java.io.InputStream;
89 import java.io.OutputStream;
90 import java.util.Properties;
92 import org.openecomp.appc.adapter.chef.chefapi.*;
93 import org.openecomp.appc.adapter.chef.chefclient.*;
96 import org.json.JSONArray;
97 import org.json.JSONException;
98 import org.json.JSONObject;
100 * This class implements the {@link ChefAdapter} interface. This interface
101 * defines the behaviors that our service provides.
103 public class ChefAdapterImpl implements ChefAdapter {
106 * The constant used to define the adapter name in the mapped diagnostic
110 //chef server Initialize variable
111 public String clientName="";
112 public String clientPrivatekey="";
113 public String chefserver="";
114 public String serverAddress="";
115 public String organizations="";
116 @SuppressWarnings("nls")
117 public static final String MDC_ADAPTER = "adapter";
120 * The constant used to define the service name in the mapped diagnostic
123 @SuppressWarnings("nls")
124 public static final String MDC_SERVICE = "service";
127 * The constant for the status code for a failed outcome
129 @SuppressWarnings("nls")
130 public static final String OUTCOME_FAILURE = "failure";
133 * The constant for the status code for a successful outcome
135 @SuppressWarnings("nls")
136 public static final String OUTCOME_SUCCESS = "success";
139 * A constant for the property token "provider" used in the structured
140 * property specifications
142 @SuppressWarnings("nls")
143 public static final String PROPERTY_PROVIDER = "provider";
146 * A constant for the property token "identity" used in the structured
147 * property specifications
149 @SuppressWarnings("nls")
150 public static final String PROPERTY_PROVIDER_IDENTITY = "identity";
153 * A constant for the property token "name" used in the structured property
156 @SuppressWarnings("nls")
157 public static final String PROPERTY_PROVIDER_NAME = "name";
160 * A constant for the property token "tenant" used in the structured
161 * property specifications
163 @SuppressWarnings("nls")
164 public static final String PROPERTY_PROVIDER_TENANT = "tenant";
167 * A constant for the property token "tenant name" used in the structured
168 * property specifications
170 @SuppressWarnings("nls")
171 public static final String PROPERTY_PROVIDER_TENANT_NAME = "name";
174 * A constant for the property token "password" used in the structured
175 * property specifications
177 @SuppressWarnings("nls")
178 public static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR
181 * A constant for the property token "userid" used in the structured
182 * property specifications
184 @SuppressWarnings("nls")
185 public static final String PROPERTY_PROVIDER_TENANT_USERID = "userid";
188 * A constant for the property token "type" used in the structured property
191 @SuppressWarnings("nls")
192 public static final String PROPERTY_PROVIDER_TYPE = "type";
195 * The name of the service to restart a server
197 @SuppressWarnings("nls")
198 public static final String PING_SERVICE = "pingServer";
201 * The logger to be used
203 private static final EELFLogger logger = EELFManager.getInstance().getLogger(ChefAdapterImpl.class);
206 * The constant for a left parenthesis
208 private static final char LPAREN = '(';
211 * The constant for a new line control code
213 private static final char NL = '\n';
216 * The constant for a single quote
218 private static final char QUOTE = '\'';
221 * The constant for a right parenthesis
223 private static final char RPAREN = ')';
226 * The constant for a space
228 private static final char SPACE = ' ';
231 * A reference to the adapter configuration object.
233 private Configuration configuration;
236 * This default constructor is used as a work around because the activator
237 * wasnt getting called
239 public ChefAdapterImpl() {
245 * This constructor is used primarily in the test cases to bypass
246 * initialization of the adapter for isolated, disconnected testing
249 * True if the adapter is to be initialized, can false if not
251 public ChefAdapterImpl(boolean initialize) {
252 configuration = ConfigurationFactory.getConfiguration();
263 public ChefAdapterImpl(Properties props) {
268 public ChefAdapterImpl(String key) {
274 * Returns the symbolic name of the adapter
276 * @return The adapter name
277 * @see org.openecomp.appc.adapter.chef.ChefAdapter#getAdapterName()
280 public String getAdapterName() {
281 return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME);
284 private void X__________________________________X() {
288 * @see org.openecomp.appc.adapter.chef.ChefAdapter#evacuateServer(java.util.Map,
289 * org.openecomp.sdnc.sli.SvcLogicContext)
292 private void X___________________________________X() {
296 * @see org.openecomp.appc.adapter.chef.ProviderAdapter#rebuildServer(java.util.Map,
297 * org.openecomp.sdnc.sli.SvcLogicContext)
305 @SuppressWarnings("nls")
307 public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) {
308 logger.info("nodeObejctBuilder");
309 String name = params.get("org.openecomp.appc.instance.nodeobject.name");
310 String normal = params.get("org.openecomp.appc.instance.nodeobject.normal");
311 String overrides = params.get("org.openecomp.appc.instance.nodeobject.overrides");
312 String defaults = params.get("org.openecomp.appc.instance.nodeobject.defaults");
313 String run_list = params.get("org.openecomp.appc.instance.nodeobject.run_list");
314 String chef_environment = params.get("org.openecomp.appc.instance.nodeobject.chef_environment");
315 String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults
316 + "},\"chef_type\":\"node\",\"run_list\":[" + run_list + "],\"override\":{" + overrides
317 + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\""
318 + chef_environment + "\"}";
319 logger.info(nodeObject);
321 RequestContext rc = new RequestContext(ctx);
323 SvcLogicContext svcLogic = rc.getSvcLogicContext();
324 svcLogic.setAttribute("org.openecomp.appc.chef.nodeObject", nodeObject);
329 * Send get request to chef server
332 public void chefInfo(Map<String, String> params) {
333 clientName = params.get("org.openecomp.appc.instance.username");
334 serverAddress = params.get("org.openecomp.appc.instance.serverAddress");
335 organizations = params.get("org.openecomp.appc.instance.organizations");
336 chefserver = "https://" + serverAddress + "/organizations/" + organizations;
337 clientPrivatekey = "/opt/openecomp/appc/chef/" + serverAddress + "/" + organizations + "/" + clientName + ".pem";
340 public Boolean privateKeyCheck() {
341 File f = new File(clientPrivatekey);
349 @SuppressWarnings("nls")
351 public void retrieveData(Map<String, String> params, SvcLogicContext ctx) {
352 String contextData = "someValue";
353 String allConfigData = params.get("org.openecomp.appc.instance.allConfig");
354 String key = params.get("org.openecomp.appc.instance.key");
355 String dgContext = params.get("org.openecomp.appc.instance.dgContext");
356 JSONObject josnConfig = new JSONObject(allConfigData);
358 contextData = josnConfig.getString(key);
359 } catch (Exception ex) {
361 contextData = josnConfig.getJSONObject(key).toString();
362 } catch (Exception exc) {
363 contextData = josnConfig.getJSONArray(key).toString();
367 RequestContext rc = new RequestContext(ctx);
369 SvcLogicContext svcLogic = rc.getSvcLogicContext();
370 svcLogic.setAttribute(dgContext, contextData);
373 @SuppressWarnings("nls")
375 public void combineStrings(Map<String, String> params, SvcLogicContext ctx) {
377 String String1 = params.get("org.openecomp.appc.instance.String1");
378 String String2 = params.get("org.openecomp.appc.instance.String2");
379 String dgContext = params.get("org.openecomp.appc.instance.dgContext");
380 String contextData = String1 + String2;
381 RequestContext rc = new RequestContext(ctx);
383 SvcLogicContext svcLogic = rc.getSvcLogicContext();
384 svcLogic.setAttribute(dgContext, contextData);
389 * Send GET request to chef server
392 @SuppressWarnings("nls")
394 public void chefGet(Map<String, String> params, SvcLogicContext ctx) {
395 logger.info("chef get method");
397 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
398 RequestContext rc = new RequestContext(ctx);
401 String message = null;
402 if (privateKeyCheck()) {
403 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
404 ApiMethod am = cac.get(chefAction);
406 code = am.getReturnCode();
407 message = am.getResponseBodyAsString();
410 message = "Cannot find the private key in the APPC file system, please load the private key to "
413 chefServerResult(rc, Integer.toString(code), message);
418 * Send PUT request to chef server
421 @SuppressWarnings("nls")
423 public void chefPut(Map<String, String> params, SvcLogicContext ctx) {
425 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
426 String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody");
427 RequestContext rc = new RequestContext(ctx);
430 String message = null;
431 if (privateKeyCheck()) {
432 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
434 ApiMethod am = cac.put(chefAction).body(CHEF_NODE_STR);
436 code = am.getReturnCode();
437 message = am.getResponseBodyAsString();
440 message = "Cannot find the private key in the APPC file system, please load the private key to "
443 logger.info(code + " " + message);
444 chefServerResult(rc, Integer.toString(code), message);
449 * Send Post request to chef server
452 @SuppressWarnings("nls")
454 public void chefPost(Map<String, String> params, SvcLogicContext ctx) {
456 logger.info("chef Post method");
457 logger.info(clientName + " " + clientPrivatekey + " " + chefserver + " " + organizations);
458 String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody");
459 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
460 RequestContext rc = new RequestContext(ctx);
463 String message = null;
464 // should load pem from somewhere else
465 if (privateKeyCheck()) {
466 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
468 // need pass path into it
470 ApiMethod am = cac.post(chefAction).body(CHEF_NODE_STR);
472 code = am.getReturnCode();
473 message = am.getResponseBodyAsString();
476 message = "Cannot find the private key in the APPC file system, please load the private key to "
479 logger.info(code + " " + message);
480 chefServerResult(rc, Integer.toString(code), message);
484 * Send delete request to chef server
487 @SuppressWarnings("nls")
489 public void chefDelete(Map<String, String> params, SvcLogicContext ctx) {
490 logger.info("chef delete method");
492 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
493 RequestContext rc = new RequestContext(ctx);
496 String message = null;
497 if (privateKeyCheck()) {
498 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
499 ApiMethod am = cac.delete(chefAction);
501 code = am.getReturnCode();
502 message = am.getResponseBodyAsString();
505 message = "Cannot find the private key in the APPC file system, please load the private key to "
508 logger.info(code + " " + message);
509 chefServerResult(rc, Integer.toString(code), message);
514 * Trigger target vm run chef
517 @SuppressWarnings("nls")
519 public void trigger(Map<String, String> params, SvcLogicContext ctx) {
520 logger.info("Run trigger method");
521 String tVmIp = params.get("org.openecomp.appc.instance.ip");
522 RequestContext rc = new RequestContext(ctx);
526 HttpGet httpGet = new HttpGet(tVmIp);
527 HttpClient httpClient = HttpClients.createDefault();
528 HttpResponse response = null;
529 response = httpClient.execute(httpGet);
530 int responseCode=response.getStatusLine().getStatusCode();
531 HttpEntity entity = response.getEntity();
532 String responseOutput=EntityUtils.toString(entity);
533 chefClientResult(rc,Integer.toString(responseCode),responseOutput);
535 } catch (Exception ex) {
536 doFailure(rc, 500 , ex.toString());
541 @SuppressWarnings("nls")
543 public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) {
545 String jobID = params.get("org.openecomp.appc.instance.jobid");
546 int retryTimes = Integer.parseInt(params.get("org.openecomp.appc.instance.retryTimes"));
547 int retryInterval = Integer.parseInt(params.get("org.openecomp.appc.instance.retryInterval"));
548 String chefAction = "/pushy/jobs/" + jobID;
550 RequestContext rc = new RequestContext(ctx);
552 SvcLogicContext svcLogic = rc.getSvcLogicContext();
555 for (int i = 0; i < retryTimes; i++) {
557 Thread.sleep(retryInterval); // 1000 milliseconds is one second.
558 } catch (InterruptedException ex) {
559 Thread.currentThread().interrupt();
561 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
562 ApiMethod am = cac.get(chefAction);
564 int code = am.getReturnCode();
565 message = am.getResponseBodyAsString();
566 JSONObject obj = new JSONObject(message);
567 status = obj.getString("status");
568 if (!status.equals("running")) {
569 logger.info(i + " time " + code + " " + status);
574 if (status.equals("complete")) {
575 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "200");
576 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
578 if (status.equals("running")) {
579 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "202");
580 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", "chef client runtime out");
582 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "500");
583 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
589 @SuppressWarnings("nls")
591 public void pushJob(Map<String, String> params, SvcLogicContext ctx) {
593 String pushRequest = params.get("org.openecomp.appc.instance.pushRequest");
594 String chefAction = "/pushy/jobs";
595 RequestContext rc = new RequestContext(ctx);
597 SvcLogicContext svcLogic = rc.getSvcLogicContext();
598 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
599 ApiMethod am = cac.post(chefAction).body(pushRequest);
602 int code = am.getReturnCode();
603 String message = am.getResponseBodyAsString();
605 int startIndex = message.indexOf("jobs") + 6;
606 int endIndex = message.length() - 2;
607 String jobID = message.substring(startIndex, endIndex);
608 svcLogic.setAttribute("org.openecomp.appc.jobID", jobID);
611 chefServerResult(rc, Integer.toString(code), message);
615 @SuppressWarnings("static-method")
616 private void doFailure(RequestContext rc, int code, String message) {
617 SvcLogicContext svcLogic = rc.getSvcLogicContext();
618 String msg = (message == null) ? Integer.toString(code) : message;
619 if (msg.contains("\n")) {
620 msg = msg.substring(msg.indexOf("\n"));
625 status = Integer.toString(code);
626 } catch (Exception e) {
629 svcLogic.setAttribute("org.openecomp.appc.chefAgent.code", status);
630 svcLogic.setAttribute("org.openecomp.appc.chefAgent.message", msg);
635 * The request context that manages the state and recovery of the
636 * request for the life of its processing.
639 @SuppressWarnings("static-method")
640 private void doSuccess(RequestContext rc) {
641 SvcLogicContext svcLogic = rc.getSvcLogicContext();
642 svcLogic.setAttribute("org.openecomp.appc.chefAgent.code", "200");
646 @SuppressWarnings("static-method")
647 private void chefServerResult(RequestContext rc, String code ,String message) {
648 String msg = (message == null) ? " " : message;
649 SvcLogicContext svcLogic = rc.getSvcLogicContext();
650 svcLogic.setStatus(OUTCOME_SUCCESS);
651 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", code);
652 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
655 @SuppressWarnings("static-method")
656 private void chefClientResult(RequestContext rc, String code ,String message) {
657 String msg = (message == null) ? " " : message;
658 SvcLogicContext svcLogic = rc.getSvcLogicContext();
659 svcLogic.setStatus(OUTCOME_SUCCESS);
660 svcLogic.setAttribute("org.openecomp.appc.chefClientResult.code", code);
661 svcLogic.setAttribute("org.openecomp.appc.chefClientResult.message", message);
665 * initialize the provider adapter by building the context cache
667 private void initialize() {
668 configuration = ConfigurationFactory.getConfiguration();
669 //need to fetch data from appc configurator or form some file in the appc vms
670 clientName="testnode";
671 clientPrivatekey="/etc/chef/client.pem";
672 serverAddress="http://example.com";
673 organizations="test";
674 chefserver=serverAddress+"/organizations/"+organizations;
675 logger.info("Initialize Chef Adapter");
678 private void initialize(String key) {
679 configuration = ConfigurationFactory.getConfiguration();
680 //need to fetch data from appc configurator or form some file in the appc vms
681 clientName="testnode";
682 clientPrivatekey=key;
683 serverAddress="http://example.com";
684 organizations="test";
685 chefserver=serverAddress+"/organizations/"+organizations;
686 logger.info("Initialize Chef Adapter");