2 * ============LICENSE_START=======================================================
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.appc.oam;
27 import org.openecomp.appc.Constants;
28 import org.openecomp.appc.configuration.Configuration;
29 import org.openecomp.appc.configuration.ConfigurationFactory;
30 import org.openecomp.appc.exceptions.APPCException;
31 import org.openecomp.appc.executor.objects.Params;
32 import org.openecomp.appc.i18n.Msg;
33 import org.openecomp.appc.logging.LoggingConstants;
34 import org.openecomp.appc.logging.LoggingUtils;
35 import org.openecomp.appc.metricservice.MetricRegistry;
36 import org.openecomp.appc.metricservice.MetricService;
37 import org.openecomp.appc.metricservice.metric.Metric;
38 import org.openecomp.appc.requesthandler.LCMStateManager;
39 import org.openecomp.appc.requesthandler.RequestHandler;
40 import com.att.eelf.configuration.EELFLogger;
41 import com.att.eelf.configuration.EELFManager;
42 import com.att.eelf.i18n.EELFResourceManager;
43 import com.google.common.util.concurrent.Futures;
44 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
45 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
46 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
47 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
48 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.*;
49 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.common.header.CommonHeader;
50 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.Metrics;
51 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.MetricsBuilder;
52 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValues;
53 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.get.metrics.output.metrics.KpiValuesBuilder;
54 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.Status;
55 import org.opendaylight.yang.gen.v1.org.openecomp.appc.oam.rev170303.status.StatusBuilder;
56 import org.opendaylight.yangtools.yang.common.RpcError;
57 import org.opendaylight.yangtools.yang.common.RpcResult;
58 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
59 import org.osgi.framework.Bundle;
60 import org.osgi.framework.BundleContext;
61 import org.osgi.framework.FrameworkUtil;
62 import org.osgi.framework.ServiceReference;
65 import java.net.InetAddress;
67 import java.util.concurrent.*;
69 import org.openecomp.appc.oam.messageadapter.*;
72 import static com.att.eelf.configuration.Configuration.*;
74 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
75 import org.osgi.framework.BundleContext;
76 import org.osgi.framework.FrameworkUtil;
77 import org.osgi.framework.ServiceReference;
79 import java.util.ArrayList;
80 import java.util.List;
82 import java.util.Properties;
83 import java.util.concurrent.Executors;
84 import java.util.concurrent.Future;
87 public class AppcOam implements AutoCloseable, AppcOamService {
89 private Configuration configuration = ConfigurationFactory.getConfiguration();
90 private final EELFLogger logger = EELFManager.getInstance().getLogger(AppcOam.class);
92 private boolean isMetricEnabled = false;
95 private final ScheduledExecutorService scheduledExecutorService;
97 private volatile ScheduledFuture<?> outstandingLCMRequestMonitorSheduledFuture;
100 private MessageAdapter messageAdapter;
104 * The ODL data store broker. Provides access to a conceptual data tree store and also provides the ability to
105 * subscribe for changes to data under a given branch of the tree.
107 private DataBroker dataBroker;
110 * ODL Notification Service that provides publish/subscribe capabilities for YANG modeled notifications.
112 private NotificationProviderService notificationService;
115 * Provides a registry for Remote Procedure Call (RPC) service implementations. The RPCs are defined in YANG models.
117 private RpcProviderRegistry rpcRegistry;
120 * Represents our RPC implementation registration
122 private BindingAwareBroker.RpcRegistration<AppcOamService> rpcRegistration;
137 * @param notificationProviderService
138 * @param rpcProviderRegistry
143 public AppcOam(DataBroker dataBroker, NotificationProviderService notificationProviderService,
144 RpcProviderRegistry rpcProviderRegistry) {
146 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
147 logger.info(Msg.COMPONENT_INITIALIZING, appName, "oam");
149 this.dataBroker = dataBroker;
150 this.notificationService = notificationProviderService;
151 this.rpcRegistry = rpcProviderRegistry;
153 if (this.rpcRegistry != null) {
154 rpcRegistration = rpcRegistry.addRpcImplementation(AppcOamService.class, this);
157 Properties properties = configuration.getProperties();
158 if (properties != null && properties.getProperty("metric.enabled") != null) {
159 isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
163 messageAdapter = new MessageAdapter();
164 messageAdapter.init();
167 scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(
171 public Thread newThread(Runnable runnable) {
172 Bundle bundle = FrameworkUtil.getBundle(AppcOam.class);
173 return new Thread(runnable,bundle.getSymbolicName() + " scheduledExecutor");
178 logger.info(Msg.COMPONENT_INITIALIZED, appName, "oam");
182 * Implements the close of the service
184 * @see AutoCloseable#close()
186 @SuppressWarnings("nls")
188 public void close() throws Exception {
189 String appName = configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
190 logger.info(Msg.COMPONENT_TERMINATING, appName, "oam");
191 scheduledExecutorService.shutdown();
192 if (rpcRegistration != null) {
193 rpcRegistration.close();
195 logger.info(Msg.COMPONENT_TERMINATED, appName, "oam");
199 public Future<RpcResult<GetMetricsOutput>> getMetrics() {
201 GetMetricsOutputBuilder outputBuilder = new GetMetricsOutputBuilder();
203 if (!isMetricEnabled){
204 logger.error("Metric Service not enabled returning failure");
205 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not enabled").build();
206 return Futures.immediateFuture(result);
209 MetricService metricService = null;
211 metricService = getService(MetricService.class);
212 } catch (APPCException e){
213 logger.error("MetricService not found",e);
214 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"Metric Service not found").build();
215 return Futures.immediateFuture(result);
217 Map<String,MetricRegistry> allMetricRegitry = metricService.getAllRegistry();
219 if(allMetricRegitry == null || allMetricRegitry.isEmpty()){
220 logger.error("No metrics registered returning failure");
221 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(false).withError(RpcError.ErrorType.APPLICATION,"No metrics Registered").build();
222 return Futures.immediateFuture(result);
224 List<Metrics> metricsList = new ArrayList<>();
226 logger.debug("Iterating metric registry list");
227 for (MetricRegistry metricRegistry : allMetricRegitry.values() ) {
228 logger.debug("Iterating metric registry :" + metricRegistry.toString());
229 Metric[] metrics = metricRegistry.metrics() ;
230 if(metrics!= null && metrics.length >0) {
231 logger.debug("Iterating though metrics in registry");
232 for (Metric metric : metrics) {
233 logger.debug("Iterating though metrics: "+ metric.name());
234 MetricsBuilder metricsBuilder = new MetricsBuilder();
235 metricsBuilder.setKpiName(metric.name());
236 metricsBuilder.setLastResetTime(metric.getLastModified());
237 List<KpiValues> kpiList = new ArrayList<>();
238 Map<String, String> metricsOutput = metric.getMetricsOutput();
239 for (Map.Entry<String, String> kpi : metricsOutput.entrySet()) {
240 KpiValuesBuilder kpiValuesBuilder = new KpiValuesBuilder();
241 kpiValuesBuilder.setName(kpi.getKey());
242 kpiValuesBuilder.setValue(kpi.getValue());
243 kpiList.add(kpiValuesBuilder.build());
245 metricsBuilder.setKpiValues(kpiList);
246 metricsList.add(metricsBuilder.build());
250 outputBuilder.setMetrics(metricsList);
251 RpcResult<GetMetricsOutput> result = RpcResultBuilder.<GetMetricsOutput> status(true).withResult(outputBuilder.build()).build();
252 return Futures.immediateFuture(result);
256 public Future<RpcResult<StopOutput>> stop(StopInput stopInput){
257 logger.debug("Input received : " + stopInput);
258 final Date startTime = new Date();
259 Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
260 final CommonHeader commonHeader = stopInput.getCommonHeader();
263 setInitialLogProperties(commonHeader,RPC.stop);
265 //Close the gate so that no more new LCM request will be excepted.
266 LCMStateManager lcmStateManager = getService(LCMStateManager.class);
267 lcmStateManager.disableLCMOperations();
268 //Begin monitoring outstanding LCM request
269 scheduleOutstandingLCMRequestMonitor(commonHeader,startTime);
270 } catch(Throwable t) {
271 status = unexpectedOAMError(t,RPC.stop);
274 LoggingUtils.auditWarn(startTime.toInstant(),
275 new Date(System.currentTimeMillis()).toInstant(),
276 String.valueOf(status.getCode()),
278 this.getClass().getCanonicalName(),
279 Msg.OAM_OPERATION_STOPPING,
282 this.clearRequestLogProperties();
285 StopOutputBuilder stopOutputBuilder = new StopOutputBuilder();
286 stopOutputBuilder.setStatus(status);
287 stopOutputBuilder.setCommonHeader(commonHeader);
288 StopOutput stopOutput = stopOutputBuilder.build();
289 return RpcResultBuilder.success(stopOutput).buildFuture();
293 public Future<RpcResult<StartOutput>> start(StartInput startInput){
294 logger.debug("Input received : " + startInput);
295 final Date startTime = new Date();
296 Status status = this.buildStatus(OAMCommandStatus.ACCEPTED);
297 final CommonHeader commonHeader = startInput.getCommonHeader();
302 setInitialLogProperties(commonHeader,RPC.start);
304 this.scheduleStartingAPPC(commonHeader,startTime);
305 } catch(Throwable t) {
306 status = unexpectedOAMError(t,RPC.start);
309 LoggingUtils.auditWarn(startTime.toInstant(),
310 new Date(System.currentTimeMillis()).toInstant(),
311 String.valueOf(status.getCode()),
313 this.getClass().getCanonicalName(),
314 Msg.OAM_OPERATION_STARTING,
317 this.clearRequestLogProperties();
320 StartOutputBuilder startOutputBuilder = new StartOutputBuilder();
321 startOutputBuilder.setStatus(status);
322 startOutputBuilder.setCommonHeader(commonHeader);
323 StartOutput startOutput = startOutputBuilder.build();
324 return RpcResultBuilder.success(startOutput).buildFuture();
327 private <T> T getService(Class<T> _class) throws APPCException {
328 BundleContext bctx = FrameworkUtil.getBundle(_class).getBundleContext();
329 ServiceReference sref = bctx.getServiceReference(_class.getName());
331 if(logger.isTraceEnabled()) {
332 logger.debug("Using the BundleContext to fetched the service reference for " + _class.getName());
335 return (T) bctx.getService(sref);
337 throw new APPCException("Using the BundleContext failed to to fetch service reference for " + _class.getName());
341 private Status buildStatus(OAMCommandStatus osmCommandStatus){
342 StatusBuilder status = new StatusBuilder();
343 status.setCode(osmCommandStatus.getResponseCode());
344 status.setMessage(osmCommandStatus.getResponseMessage());
345 return status.build();
348 private Status buildStatus(OAMCommandStatus osmCommandStatus,Params params){
349 StatusBuilder status = new StatusBuilder();
350 status.setCode(osmCommandStatus.getResponseCode());
351 status.setMessage(osmCommandStatus.getFormattedMessage(params));
352 return status.build();
357 private void clearRequestLogProperties() {
359 MDC.remove(MDC_KEY_REQUEST_ID);
360 MDC.remove(MDC_SERVICE_INSTANCE_ID);
361 MDC.remove(MDC_SERVICE_NAME);
362 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
363 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
364 } catch (Exception e) {
369 private void setInitialLogProperties(CommonHeader commonHeader,RPC action) {
372 MDC.put(MDC_KEY_REQUEST_ID, commonHeader.getRequestId());
373 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, commonHeader.getOriginatorId());
374 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
376 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
377 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
378 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
379 MDC.put(MDC_SERVICE_NAME, action.name());
380 } catch (Exception e) {
381 logger.debug("MDC constant error",e);
383 } catch (RuntimeException e) {
389 private void storeErrorMessageToLog(Status status, String additionalMessage) {
390 LoggingUtils.logErrorMessage(
391 String.valueOf(status.getCode()),
393 LoggingConstants.TargetNames.APPC,
394 LoggingConstants.TargetNames.APPC_OAM_PROVIDER,
396 this.getClass().getCanonicalName());
399 private String getAppcName(){
400 return configuration.getProperty(Constants.PROPERTY_APPLICATION_NAME);
403 private Status unexpectedOAMError(Throwable t,RPC action){
404 final String appName = getAppcName();
406 String exceptionMessage = t.getMessage() != null ? t.getMessage() : t.toString();
408 String errorMessage = EELFResourceManager.format(Msg.OAM_OPERATION_EXCEPTION, t, appName, t.getClass().getSimpleName(), action.name(), exceptionMessage);
410 Params params = new Params().addParam("errorMsg", exceptionMessage);
411 Status status = buildStatus(
412 OAMCommandStatus.UNEXPECTED_ERROR,
416 storeErrorMessageToLog(status,errorMessage);
421 private int getInprogressLCMRequestCount() throws APPCException {
422 RequestHandler requestHandler = getService(RequestHandler.class);
424 if(requestHandler == null) {
428 int inprogressRequestCount = requestHandler.getInprogressRequestCount();
429 return inprogressRequestCount;
434 private void scheduleOutstandingLCMRequestMonitor(final CommonHeader commonHeader,final Date startTime){
437 class MyCommand implements Runnable{
439 public ScheduledFuture<?> myScheduledFuture = null;
444 setInitialLogProperties(commonHeader, RPC.stop);
447 logDebug("Executing stopping task ");
449 ScheduledFuture<?> currentScheduledFuture = AppcOam.this.outstandingLCMRequestMonitorSheduledFuture;
451 //cancel myself if I am not the current outstandingLCMRequestMonitor
452 if(currentScheduledFuture != myScheduledFuture){
453 myScheduledFuture.cancel(false);
457 Status status = buildStatus(OAMCommandStatus.SUCCESS);
462 //log status and return if there are still LCM request in progress
463 int inprogressRequestCount = getInprogressLCMRequestCount();
464 if (inprogressRequestCount > 0) {
465 logDebug("The application '%s' has '%s' outstanding LCM request to complete before coming to a complete stop. ",
467 inprogressRequestCount
472 } catch (Throwable t) {
473 status = unexpectedOAMError(t, RPC.stop);
474 myScheduledFuture.cancel(false);
478 OAMContext oamContext = new OAMContext();
479 oamContext.setRpcName(RPC.stop);
480 oamContext.setCommonHeader(commonHeader);
481 oamContext.setStatus(status);
482 messageAdapter.post(oamContext);
483 } catch(Throwable t) {
484 status = unexpectedOAMError(t,RPC.stop);
487 LoggingUtils.auditWarn(startTime.toInstant(),
488 new Date(System.currentTimeMillis()).toInstant(),
489 String.valueOf(status.getCode()),
491 this.getClass().getCanonicalName(),
492 Msg.OAM_OPERATION_STOPPED,
495 myScheduledFuture.cancel(false);
498 clearRequestLogProperties();
503 MyCommand command = new MyCommand();
505 long initialDelay = 10000;
506 long delay = initialDelay;
509 command.myScheduledFuture = scheduledExecutorService.scheduleWithFixedDelay(
513 TimeUnit.MILLISECONDS
515 this.outstandingLCMRequestMonitorSheduledFuture = command.myScheduledFuture;
521 private void scheduleStartingAPPC(final CommonHeader commonHeader,final Date startTime){
524 class MyCommand implements Runnable{
530 setInitialLogProperties(commonHeader, RPC.start);
532 logDebug("Executing starting task ");
534 Status status = buildStatus(OAMCommandStatus.SUCCESS);
537 LCMStateManager lcmStateManager = getService(LCMStateManager.class);
538 lcmStateManager.enableLCMOperations();
539 //cancel the current outstandingLCMRequestMonitor
540 outstandingLCMRequestMonitorSheduledFuture = null;
541 } catch(Throwable t) {
542 status = unexpectedOAMError(t,RPC.start);
546 OAMContext oamContext = new OAMContext();
547 oamContext.setRpcName(RPC.start);
548 oamContext.setCommonHeader(commonHeader);
549 oamContext.setStatus(status);
550 messageAdapter.post(oamContext);
551 } catch(Throwable t) {
552 status = unexpectedOAMError(t,RPC.start);
555 LoggingUtils.auditWarn(startTime.toInstant(),
556 new Date(System.currentTimeMillis()).toInstant(),
557 String.valueOf(status.getCode()),
559 this.getClass().getCanonicalName(),
560 Msg.OAM_OPERATION_STARTED,
564 clearRequestLogProperties();
569 MyCommand command = new MyCommand();
570 long initialDelay = 1000;
572 scheduledExecutorService.schedule(
575 TimeUnit.MILLISECONDS
580 private void logDebug(String message,Object... args){
581 if (logger.isDebugEnabled()) {
582 logger.debug(String.format(message,args));