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.oam;
25 import org.openecomp.appc.Constants;
26 import org.openecomp.appc.configuration.Configuration;
27 import org.openecomp.appc.configuration.ConfigurationFactory;
28 import org.openecomp.appc.exceptions.APPCException;
29 import org.openecomp.appc.executor.objects.Params;
30 import org.openecomp.appc.i18n.Msg;
31 import org.openecomp.appc.logging.LoggingConstants;
32 import org.openecomp.appc.logging.LoggingUtils;
33 import org.openecomp.appc.metricservice.MetricRegistry;
34 import org.openecomp.appc.metricservice.MetricService;
35 import org.openecomp.appc.metricservice.metric.Metric;
36 import org.openecomp.appc.requesthandler.LCMStateManager;
37 import org.openecomp.appc.requesthandler.RequestHandler;
38 import com.att.eelf.configuration.EELFLogger;
39 import com.att.eelf.configuration.EELFManager;
40 import com.att.eelf.i18n.EELFResourceManager;
41 import com.google.common.util.concurrent.Futures;
42 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
43 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
44 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
45 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
46 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.*;
47 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
48 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.Metrics;
49 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.MetricsBuilder;
50 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValues;
51 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValuesBuilder;
52 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
53 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.StatusBuilder;
54 import org.opendaylight.yangtools.yang.common.RpcError;
55 import org.opendaylight.yangtools.yang.common.RpcResult;
56 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
57 import org.osgi.framework.Bundle;
58 import org.osgi.framework.BundleContext;
59 import org.osgi.framework.FrameworkUtil;
60 import org.osgi.framework.ServiceReference;
63 import java.net.InetAddress;
65 import java.util.concurrent.*;
67 import org.openecomp.appc.oam.messageadapter.*;
70 import static com.att.eelf.configuration.Configuration.*;
72 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
73 import org.osgi.framework.BundleContext;
74 import org.osgi.framework.FrameworkUtil;
75 import org.osgi.framework.ServiceReference;
77 import java.util.ArrayList;
78 import java.util.List;
80 import java.util.Properties;
81 import java.util.concurrent.Executors;
82 import java.util.concurrent.Future;
85 public class AppcOam implements AutoCloseable, AppcOamService {
87 private Configuration configuration = ConfigurationFactory.getConfiguration();
88 private final EELFLogger logger = EELFManager.getInstance().getLogger(AppcOam.class);
90 private boolean isMetricEnabled = false;
93 private final ScheduledExecutorService scheduledExecutorService;
95 private volatile ScheduledFuture<?> outstandingLCMRequestMonitorSheduledFuture;
98 private MessageAdapter messageAdapter;
102 * The ODL data store broker. Provides access to a conceptual data tree store and also provides the ability to
103 * subscribe for changes to data under a given branch of the tree.
105 private DataBroker dataBroker;
108 * ODL Notification Service that provides publish/subscribe capabilities for YANG modeled notifications.
110 private NotificationProviderService notificationService;
113 * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined in YANG models.
115 private RpcProviderRegistry rpcRegistry;
118 * Represents our RPC implementation registration
120 private BindingAwareBroker.RpcRegistration<AppcOamService> rpcRegistration;
135 * @param notificationProviderService
136 * @param rpcProviderRegistry
141 public AppcOam(DataBroker dataBroker, NotificationProviderService notificationProviderService,
142 RpcProviderRegistry rpcProviderRegistry) {
144 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
145 logger.info(Msg.COMPONENT_INITIALIZING, appName, "oam");
147 this.dataBroker = dataBroker;
148 this.notificationService = notificationProviderService;
149 this.rpcRegistry = rpcProviderRegistry;
151 if (this.rpcRegistry != null) {
152 rpcRegistration = rpcRegistry.addRpcImplementation(AppcOamService.class, this);
155 Properties properties = configuration.getProperties();
156 if (properties != null && properties.getProperty("metric.enabled") != null) {
157 isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
161 messageAdapter = new MessageAdapter();
162 messageAdapter.init();
165 scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(
169 public Thread newThread(Runnable runnable) {
170 Bundle bundle = FrameworkUtil.getBundle(AppcOam.class);
171 return new Thread(runnable,bundle.getSymbolicName() + " scheduledExecutor");
176 logger.info(Msg.COMPONENT_INITIALIZED, appName, "oam");
180 * Implements the close of the service
182 * @see AutoCloseable#close()
184 @SuppressWarnings("nls")
186 public void close() throws Exception {
187 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
188 logger.info(Msg.COMPONENT_TERMINATING, appName, "oam");
189 scheduledExecutorService.shutdown();
190 if (rpcRegistration != null) {
191 rpcRegistration.close();
193 logger.info(Msg.COMPONENT_TERMINATED, appName, "oam");
197 public Future<RpcResult<GetMetricsOutput>> getMetrics() {
199 GetMetricsOutputBuilder outputBuilder = new GetMetricsOutputBuilder();
201 if (!isMetricEnabled){
202 logger.error("Metric Service not enabled returning failure");
203 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not enabled").build();
204 return Futures.immediateFuture(result);
207 MetricService metricService = null;
209 metricService = getService(MetricService.class);
210 } catch (APPCException e){
211 logger.error("MetricService not found",e);
212 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not found").build();
213 return Futures.immediateFuture(result);
215 Map<String,MetricRegistry> allMetricRegitry = metricService.getAllRegistry();
217 if(allMetricRegitry == null || allMetricRegitry.isEmpty()){
218 logger.error("No metrics registered returning failure");
219 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"No metrics Registered").build();
220 return Futures.immediateFuture(result);
222 List<Metrics> metricsList = new ArrayList<>();
224 logger.debug("Iterating metric registry list");
225 for (MetricRegistry metricRegistry : allMetricRegitry.values() ) {
226 logger.debug("Iterating metric registry :" + metricRegistry.toString());
227 Metric[] metrics = metricRegistry.metrics() ;
228 if(metrics!= null && metrics.length >0) {
229 logger.debug("Iterating though metrics in registry");
230 for (Metric metric : metrics) {
231 logger.debug("Iterating though metrics: "+ metric.name());
232 MetricsBuilder metricsBuilder = new MetricsBuilder();
233 metricsBuilder.setKpiName(metric.name());
234 metricsBuilder.setLastResetTime(metric.getLastModified());
235 List<KpiValues> kpiList = new ArrayList<>();
236 Map<String, String> metricsOutput = metric.getMetricsOutput();
237 for (Map.Entry<String, String> kpi : metricsOutput.entrySet()) {
238 KpiValuesBuilder kpiValuesBuilder = new KpiValuesBuilder();
239 kpiValuesBuilder.setName(kpi.getKey());
240 kpiValuesBuilder.setValue(kpi.getValue());
241 kpiList.add(kpiValuesBuilder.build());
243 metricsBuilder.setKpiValues(kpiList);
244 metricsList.add(metricsBuilder.build());
248 outputBuilder.setMetrics(metricsList);
249 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(true).withResult(outputBuilder.build()).build();
250 return Futures.immediateFuture(result);
254 public Future<RpcResult<StopOutput>> stop(StopInput stopInput){
255 logger.debug("Input received : " + stopInput);
256 final Date startTime = new Date();
257 Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
258 final CommonHeader commonHeader = stopInput.getCommonHeader();
261 setInitialLogProperties(commonHeader,RPC.stop);
263 //Close the gate so that no more new LCM request will be excepted.
264 LCMStateManager lcmStateManager = getService(LCMStateManager.class);
265 lcmStateManager.disableLCMOperations();
266 //Begin monitoring outstanding LCM request
267 scheduleOutstandingLCMRequestMonitor(commonHeader,startTime);
268 } catch(Throwable t) {
269 status = unexpectedOAMError(t,RPC.stop);
272 LoggingUtils.auditWarn(startTime.toInstant(),
273 new Date(System.currentTimeMillis()).toInstant(),
274 String.valueOf(status.getCode()),
276 this.getClass().getCanonicalName(),
277 Msg.OAM_OPERATION_STOPPING,
280 this.clearRequestLogProperties();
283 StopOutputBuilder stopOutputBuilder = new StopOutputBuilder();
284 stopOutputBuilder.setStatus(status);
285 stopOutputBuilder.setCommonHeader(commonHeader);
286 StopOutput stopOutput = stopOutputBuilder.build();
287 return RpcResultBuilder.success(stopOutput).buildFuture();
291 public Future<RpcResult<StartOutput>> start(StartInput startInput){
292 logger.debug("Input received : " + startInput);
293 final Date startTime = new Date();
294 Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
295 final CommonHeader commonHeader = startInput.getCommonHeader();
300 setInitialLogProperties(commonHeader,RPC.start);
302 this.scheduleStartingAPPC(commonHeader,startTime);
303 } catch(Throwable t) {
304 status = unexpectedOAMError(t,RPC.start);
307 LoggingUtils.auditWarn(startTime.toInstant(),
308 new Date(System.currentTimeMillis()).toInstant(),
309 String.valueOf(status.getCode()),
311 this.getClass().getCanonicalName(),
312 Msg.OAM_OPERATION_STARTING,
315 this.clearRequestLogProperties();
318 StartOutputBuilder startOutputBuilder = new StartOutputBuilder();
319 startOutputBuilder.setStatus(status);
320 startOutputBuilder.setCommonHeader(commonHeader);
321 StartOutput startOutput = startOutputBuilder.build();
322 return RpcResultBuilder.success(startOutput).buildFuture();
325 private <T> T getService(Class<T> _class) throws APPCException {
326 BundleContext bctx = FrameworkUtil.getBundle(_class).getBundleContext();
327 ServiceReference sref = bctx.getServiceReference(_class.getName());
329 if(logger.isTraceEnabled()) {
330 logger.debug("Using the BundleContext to fetched the service reference for " + _class.getName());
333 return (T) bctx.getService(sref);
335 throw new APPCException("Using the BundleContext failed to to fetch service reference for " + _class.getName());
339 private Status buildStatus(OAMCommandStatus osmCommandStatus){
340 StatusBuilder status = new StatusBuilder();
341 status.setCode(osmCommandStatus.getResponseCode());
342 status.setMessage(osmCommandStatus.getResponseMessage());
343 return status.build();
346 private Status buildStatus(OAMCommandStatus osmCommandStatus,Params params){
347 StatusBuilder status = new StatusBuilder();
348 status.setCode(osmCommandStatus.getResponseCode());
349 status.setMessage(osmCommandStatus.getFormattedMessage(params));
350 return status.build();
355 private void clearRequestLogProperties() {
357 MDC.remove(MDC_KEY_REQUEST_ID);
358 MDC.remove(MDC_SERVICE_INSTANCE_ID);
359 MDC.remove(MDC_SERVICE_NAME);
360 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
361 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
362 } catch (Exception e) {
367 private void setInitialLogProperties(CommonHeader commonHeader,RPC action) {
370 MDC.put(MDC_KEY_REQUEST_ID, commonHeader.getRequestId());
371 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, commonHeader.getOriginatorId());
372 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
374 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
375 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
376 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
377 MDC.put(MDC_SERVICE_NAME, action.name());
378 } catch (Exception e) {
379 logger.debug("MDC constant error",e);
381 } catch (RuntimeException e) {
387 private void storeErrorMessageToLog(Status status, String additionalMessage) {
388 LoggingUtils.logErrorMessage(
389 String.valueOf(status.getCode()),
391 LoggingConstants.TargetNames.APPC,
392 LoggingConstants.TargetNames.APPC_OAM_PROVIDER,
394 this.getClass().getCanonicalName());
397 private String getAppcName(){
398 return configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
401 private Status unexpectedOAMError(Throwable t,RPC action){
402 final String appName = getAppcName();
404 String exceptionMessage = t.getMessage() != null ? t.getMessage() : t.toString();
406 String errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t, appName, t.getClass().getSimpleName(), action.name(), exceptionMessage);
408 Params params = new Params().addParam("errorMsg", exceptionMessage);
409 Status status = buildStatus(
410 OAMCommandStatus.UNEXPECTED_ERROR,
414 storeErrorMessageToLog(status,errorMessage);
419 private int getInprogressLCMRequestCount() throws APPCException {
420 RequestHandler requestHandler = getService(RequestHandler.class);
422 if(requestHandler == null) {
426 int inprogressRequestCount = requestHandler.getInprogressRequestCount();
427 return inprogressRequestCount;
432 private void scheduleOutstandingLCMRequestMonitor(final CommonHeader commonHeader,final Date startTime){
435 class MyCommand implements Runnable{
437 public ScheduledFuture<?> myScheduledFuture = null;
442 setInitialLogProperties(commonHeader, RPC.stop);
445 logDebug("Executing stopping task ");
447 ScheduledFuture<?> currentScheduledFuture = AppcOam.this.outstandingLCMRequestMonitorSheduledFuture;
449 //cancel myself if I am not the current outstandingLCMRequestMonitor
450 if(currentScheduledFuture != myScheduledFuture){
451 myScheduledFuture.cancel(false);
455 Status status = buildStatus(OAMCommandStatus.SUCCESS);
460 //log status and return if there are still LCM request in progress
461 int inprogressRequestCount = getInprogressLCMRequestCount();
462 if (inprogressRequestCount > 0) {
463 logDebug("The application '%s' has '%s' outstanding LCM request to complete before coming to a complete stop. ",
465 inprogressRequestCount
470 } catch (Throwable t) {
471 status = unexpectedOAMError(t, RPC.stop);
472 myScheduledFuture.cancel(false);
476 OAMContext oamContext = new OAMContext();
477 oamContext.setRpcName(RPC.stop);
478 oamContext.setCommonHeader(commonHeader);
479 oamContext.setStatus(status);
480 messageAdapter.post(oamContext);
481 } catch(Throwable t) {
482 status = unexpectedOAMError(t,RPC.stop);
485 LoggingUtils.auditWarn(startTime.toInstant(),
486 new Date(System.currentTimeMillis()).toInstant(),
487 String.valueOf(status.getCode()),
489 this.getClass().getCanonicalName(),
490 Msg.OAM_OPERATION_STOPPED,
493 myScheduledFuture.cancel(false);
496 clearRequestLogProperties();
501 MyCommand command = new MyCommand();
503 long initialDelay = 10000;
504 long delay = initialDelay;
507 command.myScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(
511 TimeUnit.MILLISECONDS
513 this.outstandingLCMRequestMonitorSheduledFuture = command.myScheduledFuture;
519 private void scheduleStartingAPPC(final CommonHeader commonHeader,final Date startTime){
522 class MyCommand implements Runnable{
528 setInitialLogProperties(commonHeader, RPC.start);
530 logDebug("Executing starting task ");
532 Status status = buildStatus(OAMCommandStatus.SUCCESS);
535 LCMStateManager lcmStateManager = getService(LCMStateManager.class);
536 lcmStateManager.enableLCMOperations();
537 //cancel the current outstandingLCMRequestMonitor
538 outstandingLCMRequestMonitorSheduledFuture = null;
539 } catch(Throwable t) {
540 status = unexpectedOAMError(t,RPC.start);
544 OAMContext oamContext = new OAMContext();
545 oamContext.setRpcName(RPC.start);
546 oamContext.setCommonHeader(commonHeader);
547 oamContext.setStatus(status);
548 messageAdapter.post(oamContext);
549 } catch(Throwable t) {
550 status = unexpectedOAMError(t,RPC.start);
553 LoggingUtils.auditWarn(startTime.toInstant(),
554 new Date(System.currentTimeMillis()).toInstant(),
555 String.valueOf(status.getCode()),
557 this.getClass().getCanonicalName(),
558 Msg.OAM_OPERATION_STARTED,
562 clearRequestLogProperties();
567 MyCommand command = new MyCommand();
568 long initialDelay = 1000;
570 scheduledExecutorService.schedule(
573 TimeUnit.MILLISECONDS
578 private void logDebug(String message,Object... args){
579 if (logger.isDebugEnabled()) {
580 logger.debug(String.format(message,args));