2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
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=========================================================
22 package org.openecomp.appc.adapter.chef.impl;
25 import java.util.ArrayList;
26 import java.util.HashMap;
27 import java.util.List;
29 import java.util.Properties;
31 import java.util.regex.Pattern;
33 import org.glassfish.grizzly.http.util.HttpStatus;
34 import org.openecomp.appc.Constants;
35 import org.openecomp.appc.adapter.chef.ChefAdapter;
36 import org.openecomp.appc.adapter.chef.chefapi.*;
37 import org.openecomp.appc.adapter.chef.chefclient.*;
38 import org.openecomp.appc.configuration.Configuration;
39 import org.openecomp.appc.configuration.ConfigurationFactory;
40 import org.openecomp.appc.exceptions.APPCException;
41 import org.openecomp.appc.exceptions.UnknownProviderException;
42 import org.openecomp.appc.i18n.Msg;
43 import org.openecomp.appc.pool.Pool;
44 import org.openecomp.appc.pool.PoolExtensionException;
45 import org.openecomp.appc.util.StructuredPropertyHelper;
46 import org.openecomp.appc.util.StructuredPropertyHelper.Node;
47 import com.att.cdp.exceptions.ContextConnectionException;
48 import com.att.cdp.exceptions.ResourceNotFoundException;
49 import com.att.cdp.exceptions.TimeoutException;
50 import com.att.cdp.exceptions.ZoneException;
51 import com.att.cdp.pal.util.StringHelper;
52 import com.att.cdp.zones.ComputeService;
53 import com.att.cdp.zones.Context;
54 import com.att.cdp.zones.ImageService;
55 import com.att.cdp.zones.Provider;
56 import com.att.cdp.zones.model.Image;
57 import com.att.cdp.zones.model.Server;
58 import com.att.cdp.zones.model.ServerBootSource;
59 import com.att.cdp.zones.model.Server.Status;
60 import com.att.eelf.configuration.EELFLogger;
61 import com.att.eelf.configuration.EELFManager;
62 import com.att.eelf.i18n.EELFResourceManager;
63 import org.openecomp.sdnc.sli.SvcLogicContext;
66 import java.net.InetAddress;
67 import java.util.Locale;
68 import java.util.UUID;
70 import org.apache.http.*;
71 import org.apache.http.client.*;
72 import org.apache.http.client.methods.*;
73 import org.apache.http.impl.client.*;
74 import org.apache.http.util.EntityUtils;
76 import static com.att.eelf.configuration.Configuration.*;
78 import java.io.IOException;
80 import java.net.InetAddress;
82 import java.io.BufferedInputStream;
84 import java.io.FileInputStream;
85 import java.io.FileOutputStream;
86 import java.io.IOException;
87 import java.io.InputStream;
88 import java.io.OutputStream;
89 import java.util.Properties;
91 import org.openecomp.appc.adapter.chef.chefapi.*;
92 import org.openecomp.appc.adapter.chef.chefclient.*;
95 import org.json.JSONArray;
96 import org.json.JSONException;
97 import org.json.JSONObject;
99 * This class implements the {@link ChefAdapter} interface. This interface
100 * defines the behaviors that our service provides.
102 public class ChefAdapterImpl implements ChefAdapter {
105 * The constant used to define the adapter name in the mapped diagnostic
109 //chef server Initialize variable
110 public String clientName="";
111 public String clientPrivatekey="";
112 public String chefserver="";
113 public String serverAddress="";
114 public String organizations="";
115 @SuppressWarnings("nls")
116 public static final String MDC_ADAPTER = "adapter";
119 * The constant used to define the service name in the mapped diagnostic
122 @SuppressWarnings("nls")
123 public static final String MDC_SERVICE = "service";
126 * The constant for the status code for a failed outcome
128 @SuppressWarnings("nls")
129 public static final String OUTCOME_FAILURE = "failure";
132 * The constant for the status code for a successful outcome
134 @SuppressWarnings("nls")
135 public static final String OUTCOME_SUCCESS = "success";
138 * A constant for the property token "provider" used in the structured
139 * property specifications
141 @SuppressWarnings("nls")
142 public static final String PROPERTY_PROVIDER = "provider";
145 * A constant for the property token "identity" used in the structured
146 * property specifications
148 @SuppressWarnings("nls")
149 public static final String PROPERTY_PROVIDER_IDENTITY = "identity";
152 * A constant for the property token "name" used in the structured property
155 @SuppressWarnings("nls")
156 public static final String PROPERTY_PROVIDER_NAME = "name";
159 * A constant for the property token "tenant" used in the structured
160 * property specifications
162 @SuppressWarnings("nls")
163 public static final String PROPERTY_PROVIDER_TENANT = "tenant";
166 * A constant for the property token "tenant name" used in the structured
167 * property specifications
169 @SuppressWarnings("nls")
170 public static final String PROPERTY_PROVIDER_TENANT_NAME = "name";
173 * A constant for the property token "password" used in the structured
174 * property specifications
176 @SuppressWarnings("nls")
177 public static final String PROPERTY_PROVIDER_TENANT_PASSWORD = "password"; // NOSONAR
180 * A constant for the property token "userid" used in the structured
181 * property specifications
183 @SuppressWarnings("nls")
184 public static final String PROPERTY_PROVIDER_TENANT_USERID = "userid";
187 * A constant for the property token "type" used in the structured property
190 @SuppressWarnings("nls")
191 public static final String PROPERTY_PROVIDER_TYPE = "type";
194 * The name of the service to restart a server
196 @SuppressWarnings("nls")
197 public static final String PING_SERVICE = "pingServer";
200 * The logger to be used
202 private static final EELFLogger logger = EELFManager.getInstance().getLogger(ChefAdapterImpl.class);
205 * The constant for a left parenthesis
207 private static final char LPAREN = '(';
210 * The constant for a new line control code
212 private static final char NL = '\n';
215 * The constant for a single quote
217 private static final char QUOTE = '\'';
220 * The constant for a right parenthesis
222 private static final char RPAREN = ')';
225 * The constant for a space
227 private static final char SPACE = ' ';
230 * A reference to the adapter configuration object.
232 private Configuration configuration;
235 * This default constructor is used as a work around because the activator
236 * wasnt getting called
238 public ChefAdapterImpl() {
244 * This constructor is used primarily in the test cases to bypass
245 * initialization of the adapter for isolated, disconnected testing
248 * True if the adapter is to be initialized, can false if not
250 public ChefAdapterImpl(boolean initialize) {
251 configuration = ConfigurationFactory.getConfiguration();
262 public ChefAdapterImpl(Properties props) {
267 public ChefAdapterImpl(String key) {
273 * Returns the symbolic name of the adapter
275 * @return The adapter name
276 * @see org.openecomp.appc.adapter.chef.ChefAdapter#getAdapterName()
279 public String getAdapterName() {
280 return configuration.getProperty(Constants.PROPERTY_ADAPTER_NAME);
283 private void X__________________________________X() {
287 * @see org.openecomp.appc.adapter.chef.ChefAdapter#evacuateServer(java.util.Map,
288 * org.openecomp.sdnc.sli.SvcLogicContext)
291 private void X___________________________________X() {
295 * @see org.openecomp.appc.adapter.chef.ProviderAdapter#rebuildServer(java.util.Map,
296 * org.openecomp.sdnc.sli.SvcLogicContext)
304 @SuppressWarnings("nls")
306 public void nodeObejctBuilder(Map<String, String> params, SvcLogicContext ctx) {
307 logger.info("nodeObejctBuilder");
308 String name = params.get("org.openecomp.appc.instance.nodeobject.name");
309 String normal = params.get("org.openecomp.appc.instance.nodeobject.normal");
310 String overrides = params.get("org.openecomp.appc.instance.nodeobject.overrides");
311 String defaults = params.get("org.openecomp.appc.instance.nodeobject.defaults");
312 String run_list = params.get("org.openecomp.appc.instance.nodeobject.run_list");
313 String chef_environment = params.get("org.openecomp.appc.instance.nodeobject.chef_environment");
314 String nodeObject = "{\"json_class\":\"Chef::Node\",\"default\":{" + defaults
315 + "},\"chef_type\":\"node\",\"run_list\":[" + run_list + "],\"override\":{" + overrides
316 + "},\"normal\": {" + normal + "},\"automatic\":{},\"name\":\"" + name + "\",\"chef_environment\":\""
317 + chef_environment + "\"}";
318 logger.info(nodeObject);
320 RequestContext rc = new RequestContext(ctx);
322 SvcLogicContext svcLogic = rc.getSvcLogicContext();
323 svcLogic.setAttribute("org.openecomp.appc.chef.nodeObject", nodeObject);
328 * Send get request to chef server
331 public void chefInfo(Map<String, String> params) {
332 clientName = params.get("org.openecomp.appc.instance.username");
333 serverAddress = params.get("org.openecomp.appc.instance.serverAddress");
334 organizations = params.get("org.openecomp.appc.instance.organizations");
335 chefserver = "https://" + serverAddress + "/organizations/" + organizations;
336 clientPrivatekey = "/opt/openecomp/appc/chef/" + serverAddress + "/" + organizations + "/" + clientName + ".pem";
339 public Boolean privateKeyCheck() {
340 File f = new File(clientPrivatekey);
348 @SuppressWarnings("nls")
350 public void retrieveData(Map<String, String> params, SvcLogicContext ctx) {
351 String contextData = "someValue";
352 String allConfigData = params.get("org.openecomp.appc.instance.allConfig");
353 String key = params.get("org.openecomp.appc.instance.key");
354 String dgContext = params.get("org.openecomp.appc.instance.dgContext");
355 JSONObject josnConfig = new JSONObject(allConfigData);
357 contextData = josnConfig.getString(key);
358 } catch (Exception ex) {
360 contextData = josnConfig.getJSONObject(key).toString();
361 } catch (Exception exc) {
362 contextData = josnConfig.getJSONArray(key).toString();
366 RequestContext rc = new RequestContext(ctx);
368 SvcLogicContext svcLogic = rc.getSvcLogicContext();
369 svcLogic.setAttribute(dgContext, contextData);
372 @SuppressWarnings("nls")
374 public void combineStrings(Map<String, String> params, SvcLogicContext ctx) {
376 String String1 = params.get("org.openecomp.appc.instance.String1");
377 String String2 = params.get("org.openecomp.appc.instance.String2");
378 String dgContext = params.get("org.openecomp.appc.instance.dgContext");
379 String contextData = String1 + String2;
380 RequestContext rc = new RequestContext(ctx);
382 SvcLogicContext svcLogic = rc.getSvcLogicContext();
383 svcLogic.setAttribute(dgContext, contextData);
388 * Send GET request to chef server
391 @SuppressWarnings("nls")
393 public void chefGet(Map<String, String> params, SvcLogicContext ctx) {
394 logger.info("chef get method");
396 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
397 RequestContext rc = new RequestContext(ctx);
400 String message = null;
401 if (privateKeyCheck()) {
402 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
403 ApiMethod am = cac.get(chefAction);
405 code = am.getReturnCode();
406 message = am.getResponseBodyAsString();
409 message = "Cannot find the private key in the APPC file system, please load the private key to "
412 chefServerResult(rc, Integer.toString(code), message);
417 * Send PUT request to chef server
420 @SuppressWarnings("nls")
422 public void chefPut(Map<String, String> params, SvcLogicContext ctx) {
424 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
425 String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody");
426 RequestContext rc = new RequestContext(ctx);
429 String message = null;
430 if (privateKeyCheck()) {
431 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
433 ApiMethod am = cac.put(chefAction).body(CHEF_NODE_STR);
435 code = am.getReturnCode();
436 message = am.getResponseBodyAsString();
439 message = "Cannot find the private key in the APPC file system, please load the private key to "
442 logger.info(code + " " + message);
443 chefServerResult(rc, Integer.toString(code), message);
448 * Send Post request to chef server
451 @SuppressWarnings("nls")
453 public void chefPost(Map<String, String> params, SvcLogicContext ctx) {
455 logger.info("chef Post method");
456 logger.info(clientName + " " + clientPrivatekey + " " + chefserver + " " + organizations);
457 String CHEF_NODE_STR = params.get("org.openecomp.appc.instance.chefRequestBody");
458 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
459 RequestContext rc = new RequestContext(ctx);
462 String message = null;
463 // should load pem from somewhere else
464 if (privateKeyCheck()) {
465 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
467 // need pass path into it
469 ApiMethod am = cac.post(chefAction).body(CHEF_NODE_STR);
471 code = am.getReturnCode();
472 message = am.getResponseBodyAsString();
475 message = "Cannot find the private key in the APPC file system, please load the private key to "
478 logger.info(code + " " + message);
479 chefServerResult(rc, Integer.toString(code), message);
483 * Send delete request to chef server
486 @SuppressWarnings("nls")
488 public void chefDelete(Map<String, String> params, SvcLogicContext ctx) {
489 logger.info("chef delete method");
491 String chefAction = params.get("org.openecomp.appc.instance.chefAction");
492 RequestContext rc = new RequestContext(ctx);
495 String message = null;
496 if (privateKeyCheck()) {
497 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
498 ApiMethod am = cac.delete(chefAction);
500 code = am.getReturnCode();
501 message = am.getResponseBodyAsString();
504 message = "Cannot find the private key in the APPC file system, please load the private key to "
507 logger.info(code + " " + message);
508 chefServerResult(rc, Integer.toString(code), message);
513 * Trigger target vm run chef
516 @SuppressWarnings("nls")
518 public void trigger(Map<String, String> params, SvcLogicContext ctx) {
519 logger.info("Run trigger method");
520 String tVmIp = params.get("org.openecomp.appc.instance.ip");
521 RequestContext rc = new RequestContext(ctx);
525 HttpGet httpGet = new HttpGet(tVmIp);
526 HttpClient httpClient = HttpClients.createDefault();
527 HttpResponse response = null;
528 response = httpClient.execute(httpGet);
529 int responseCode=response.getStatusLine().getStatusCode();
530 HttpEntity entity = response.getEntity();
531 String responseOutput=EntityUtils.toString(entity);
532 chefClientResult(rc,Integer.toString(responseCode),responseOutput);
534 } catch (Exception ex) {
535 doFailure(rc, 500 , ex.toString());
540 @SuppressWarnings("nls")
542 public void checkPushJob(Map<String, String> params, SvcLogicContext ctx) {
544 String jobID = params.get("org.openecomp.appc.instance.jobid");
545 int retryTimes = Integer.parseInt(params.get("org.openecomp.appc.instance.retryTimes"));
546 int retryInterval = Integer.parseInt(params.get("org.openecomp.appc.instance.retryInterval"));
547 String chefAction = "/pushy/jobs/" + jobID;
549 RequestContext rc = new RequestContext(ctx);
551 SvcLogicContext svcLogic = rc.getSvcLogicContext();
554 for (int i = 0; i < retryTimes; i++) {
556 Thread.sleep(retryInterval); // 1000 milliseconds is one second.
557 } catch (InterruptedException ex) {
558 Thread.currentThread().interrupt();
560 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
561 ApiMethod am = cac.get(chefAction);
563 int code = am.getReturnCode();
564 message = am.getResponseBodyAsString();
565 JSONObject obj = new JSONObject(message);
566 status = obj.getString("status");
567 if (!status.equals("running")) {
568 logger.info(i + " time " + code + " " + status);
573 if (status.equals("complete")) {
574 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "200");
575 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
577 if (status.equals("running")) {
578 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "202");
579 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", "chef client runtime out");
581 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", "500");
582 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
588 @SuppressWarnings("nls")
590 public void pushJob(Map<String, String> params, SvcLogicContext ctx) {
592 String pushRequest = params.get("org.openecomp.appc.instance.pushRequest");
593 String chefAction = "/pushy/jobs";
594 RequestContext rc = new RequestContext(ctx);
596 SvcLogicContext svcLogic = rc.getSvcLogicContext();
597 ChefApiClient cac = new ChefApiClient(clientName, clientPrivatekey, chefserver, organizations);
598 ApiMethod am = cac.post(chefAction).body(pushRequest);
601 int code = am.getReturnCode();
602 String message = am.getResponseBodyAsString();
604 int startIndex = message.indexOf("jobs") + 6;
605 int endIndex = message.length() - 2;
606 String jobID = message.substring(startIndex, endIndex);
607 svcLogic.setAttribute("org.openecomp.appc.jobID", jobID);
610 chefServerResult(rc, Integer.toString(code), message);
614 @SuppressWarnings("static-method")
615 private void doFailure(RequestContext rc, int code, String message) {
616 SvcLogicContext svcLogic = rc.getSvcLogicContext();
617 String msg = (message == null) ? Integer.toString(code) : message;
618 if (msg.contains("\n")) {
619 msg = msg.substring(msg.indexOf("\n"));
624 status = Integer.toString(code);
625 } catch (Exception e) {
628 svcLogic.setAttribute("org.openecomp.appc.chefAgent.code", status);
629 svcLogic.setAttribute("org.openecomp.appc.chefAgent.message", msg);
634 * The request context that manages the state and recovery of the
635 * request for the life of its processing.
638 @SuppressWarnings("static-method")
639 private void doSuccess(RequestContext rc) {
640 SvcLogicContext svcLogic = rc.getSvcLogicContext();
641 svcLogic.setAttribute("org.openecomp.appc.chefAgent.code", "200");
645 @SuppressWarnings("static-method")
646 private void chefServerResult(RequestContext rc, String code ,String message) {
647 String msg = (message == null) ? " " : message;
648 SvcLogicContext svcLogic = rc.getSvcLogicContext();
649 svcLogic.setStatus(OUTCOME_SUCCESS);
650 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.code", code);
651 svcLogic.setAttribute("org.openecomp.appc.chefServerResult.message", message);
654 @SuppressWarnings("static-method")
655 private void chefClientResult(RequestContext rc, String code ,String message) {
656 String msg = (message == null) ? " " : message;
657 SvcLogicContext svcLogic = rc.getSvcLogicContext();
658 svcLogic.setStatus(OUTCOME_SUCCESS);
659 svcLogic.setAttribute("org.openecomp.appc.chefClientResult.code", code);
660 svcLogic.setAttribute("org.openecomp.appc.chefClientResult.message", message);
664 * initialize the provider adapter by building the context cache
666 private void initialize() {
667 configuration = ConfigurationFactory.getConfiguration();
668 //need to fetch data from appc configurator or form some file in the appc vms
669 clientName="testnode";
670 clientPrivatekey="/etc/chef/client.pem";
671 serverAddress="http://example.com";
672 organizations="test";
673 chefserver=serverAddress+"/organizations/"+organizations;
674 logger.info("Initialize Chef Adapter");
677 private void initialize(String key) {
678 configuration = ConfigurationFactory.getConfiguration();
679 //need to fetch data from appc configurator or form some file in the appc vms
680 clientName="testnode";
681 clientPrivatekey=key;
682 serverAddress="http://example.com";
683 organizations="test";
684 chefserver=serverAddress+"/organizations/"+organizations;
685 logger.info("Initialize Chef Adapter");