First part of onap rename
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / openecomp / appc / requesthandler / impl / AbstractRequestHandlerImpl.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.requesthandler.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.att.eelf.i18n.EELFResourceManager;
30 import org.apache.commons.lang.ObjectUtils;
31 import org.onap.appc.requesthandler.constant.Constants;
32 import org.onap.appc.configuration.Configuration;
33 import org.onap.appc.configuration.ConfigurationFactory;
34 import org.onap.appc.domainmodel.lcm.*;
35 import org.onap.appc.exceptions.APPCException;
36 import org.onap.appc.executor.CommandExecutor;
37 import org.onap.appc.executor.UnstableVNFException;
38 import org.onap.appc.executor.objects.LCMCommandStatus;
39 import org.onap.appc.executor.objects.Params;
40 import org.onap.appc.executor.objects.UniqueRequestIdentifier;
41 import org.onap.appc.i18n.Msg;
42 import org.onap.appc.lifecyclemanager.objects.LifecycleException;
43 import org.onap.appc.lifecyclemanager.objects.NoTransitionDefinedException;
44 import org.onap.appc.logging.LoggingConstants;
45 import org.onap.appc.logging.LoggingUtils;
46 import org.onap.appc.messageadapter.MessageAdapter;
47 import org.onap.appc.messageadapter.impl.MessageAdapterImpl;
48 import org.onap.appc.metricservice.MetricRegistry;
49 import org.onap.appc.metricservice.MetricService;
50 import org.onap.appc.metricservice.metric.DispatchingFuntionMetric;
51 import org.onap.appc.metricservice.metric.Metric;
52 import org.onap.appc.metricservice.metric.MetricType;
53 import org.onap.appc.metricservice.policy.PublishingPolicy;
54 import org.onap.appc.metricservice.publisher.LogPublisher;
55 import org.onap.appc.requesthandler.RequestHandler;
56 import org.onap.appc.requesthandler.exceptions.*;
57 import org.onap.appc.requesthandler.helper.RequestRegistry;
58 import org.onap.appc.requesthandler.helper.RequestValidator;
59 import org.onap.appc.requesthandler.objects.RequestHandlerInput;
60 import org.onap.appc.requesthandler.objects.RequestHandlerOutput;
61 import org.onap.appc.transactionrecorder.TransactionRecorder;
62 import org.onap.appc.transactionrecorder.objects.TransactionRecord;
63 import org.osgi.framework.BundleContext;
64 import org.osgi.framework.FrameworkUtil;
65 import org.osgi.framework.ServiceReference;
66 import org.slf4j.MDC;
67
68 import java.net.InetAddress;
69 import java.time.Instant;
70 import java.util.HashMap;
71 import java.util.Properties;
72
73 import static com.att.eelf.configuration.Configuration.*;
74
75 /**
76  * This class provides application logic for the Request/Response Handler Component.
77  *
78  */
79 public abstract class AbstractRequestHandlerImpl implements RequestHandler {
80
81     private RequestValidator requestValidator;
82
83
84
85     private RequestRegistry requestRegistry;
86
87     private CommandExecutor commandExecutor;
88
89     private TransactionRecorder transactionRecorder;
90
91     private MessageAdapter messageAdapter;
92
93     private static MetricRegistry metricRegistry;
94
95     private boolean isMetricEnabled = false;
96
97     protected static final Configuration configuration = ConfigurationFactory.getConfiguration();
98
99     private static final EELFLogger logger = EELFManager.getInstance().getLogger(AbstractRequestHandlerImpl.class);
100
101     public AbstractRequestHandlerImpl() {
102         requestRegistry = new RequestRegistry();
103         messageAdapter = new MessageAdapterImpl();
104         messageAdapter.init();
105         Properties properties = configuration.getProperties();
106         if (properties != null && properties.getProperty("metric.enabled") != null) {
107             isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
108         }
109         if (isMetricEnabled) {
110             initMetric();
111         }
112     }
113
114     public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
115         this.transactionRecorder = transactionRecorder;
116     }
117
118     public void setRequestValidator(RequestValidator requestValidator) {
119         this.requestValidator = requestValidator;
120     }
121
122     public void setMessageAdapter(MessageAdapter messageAdapter) {
123         this.messageAdapter = messageAdapter;
124     }
125
126
127
128     public void setRequestRegistry(RequestRegistry requestRegistry) {
129         this.requestRegistry = requestRegistry;
130     }
131
132     public void setCommandExecutor(CommandExecutor commandExecutor) {
133         this.commandExecutor = commandExecutor;
134     }
135
136
137     /**
138      * It receives requests from the north-bound REST API (Communication) Layer and
139      * performs following validations.
140      * 1. VNF exists in A&AI for the given targetID (VnfID)
141      * 2. For the current VNF  Orchestration Status, the command can be executed
142      * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
143      * If any of the validation fails, it returns appropriate response
144      *
145      * @param input RequestHandlerInput object which contains request header and  other request parameters like command , target Id , payload etc.
146      * @return response for request as enum with Return code and message.
147      */
148     @Override
149     public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
150         if (logger.isTraceEnabled())
151             logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
152         Params params ;
153         String vnfId, vnfType = null, errorMessage = null;
154         Instant startTime = Instant.now();
155         RequestHandlerOutput output = null;
156         setInitialLogProperties(input.getRequestContext());
157
158         RuntimeContext runtimeContext = new RuntimeContext();
159         runtimeContext.setRequestContext(input.getRequestContext());
160         runtimeContext.setTimeStart(startTime);
161         runtimeContext.setRpcName(input.getRpcName());
162
163         final ResponseContext responseContext = new ResponseContext();
164         responseContext.setStatus(new Status(0,""));
165         responseContext.setAdditionalContext(new HashMap<>(4));
166         responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
167         runtimeContext.setResponseContext(responseContext);
168         runtimeContext.getResponseContext().setStatus(new Status(0,""));
169
170         vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
171
172         try {
173
174             requestValidator.validateRequest(runtimeContext);
175
176             handleRequest(runtimeContext);
177
178             final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
179             if (statusCode % 100 == 2 || statusCode % 100 == 3) {
180                 createTransactionRecord(runtimeContext);
181             }
182             output = new RequestHandlerOutput();
183             output.setResponseContext(runtimeContext.getResponseContext());
184
185         } catch (VNFNotFoundException e) {
186             errorMessage = e.getMessage();
187             String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
188             storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
189             params = new Params().addParam("vnfId", vnfId);
190             output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
191         } catch (NoTransitionDefinedException e) {
192             errorMessage = e.getMessage();
193             String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
194             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
195             output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
196             storeErrorMessageToLog(runtimeContext,
197                     LoggingConstants.TargetNames.APPC,
198                     LoggingConstants.TargetNames.STATE_MACHINE,
199                     logMessage);
200         } catch (LifecycleException e) {
201             errorMessage = e.getMessage();
202             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
203             output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_VNF_STATE, params);
204         } catch (UnstableVNFException e) {
205             errorMessage = e.getMessage();
206             params = new Params().addParam("vnfId", vnfId);
207             output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
208         } catch (WorkflowNotFoundException e) {
209             errorMessage = e.getMessage();
210             String vnfTypeVersion = e.vnfTypeVersion;
211             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
212             output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
213         } catch (DGWorkflowNotFoundException e) {
214             errorMessage = e.getMessage();
215             String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
216             storeErrorMessageToLog(runtimeContext,
217                     LoggingConstants.TargetNames.APPC,
218                     LoggingConstants.TargetNames.WORKFLOW_MANAGER,
219                     logMessage);
220             params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
221                     .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
222             output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
223         } catch (RequestExpiredException e) {
224             errorMessage = e.getMessage();
225             params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
226             output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
227         } catch (InvalidInputException e) {
228             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
229             params = new Params().addParam("errorMsg", errorMessage);
230             output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
231         } catch (DuplicateRequestException e) {
232             errorMessage = e.getMessage();
233             output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
234         } catch (MissingVNFDataInAAIException e) {
235             params = new Params().addParam("attributeName",e.getMissingAttributeName())
236                     .addParam("vnfId",vnfId);
237             output = buildRequestHandlerOutput(LCMCommandStatus.MISSING_VNF_DATA_IN_AAI,params);
238             errorMessage = output.getResponseContext().getStatus().getMessage();
239         } catch (LCMOperationsDisabledException e) {
240             errorMessage = e.getMessage();
241             params = new Params().addParam("errorMsg", errorMessage);
242             output = buildRequestHandlerOutput(LCMCommandStatus.REJECTED, params);
243         } catch (Exception e) {
244             storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
245             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
246             params = new Params().addParam("errorMsg", errorMessage);
247             output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
248         } finally {
249             try {
250                 if (logger.isDebugEnabled() && errorMessage != null)
251                     logger.debug("error occurred in handleRequest " + errorMessage);
252                 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
253                 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
254
255                 runtimeContext.setResponseContext(output.getResponseContext());
256                 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
257                     if (isMetricEnabled) {
258                         if((output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode())) {
259                             ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
260                         }else {
261                             ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
262                         }
263                     }
264                     removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
265                 }
266             } finally {
267                 storeAuditLogRecord(runtimeContext);
268                 storeMetricLogRecord(runtimeContext);
269                 clearRequestLogProperties();
270             }
271         }
272         if (logger.isTraceEnabled()) {
273             logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
274         }
275         return output;
276     }
277
278     protected void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
279         LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
280                         String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
281                 runtimeContext.getResponseContext().getStatus() != null ?
282                         String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
283                 targetEntity,
284                 targetServiceName,
285                 additionalMessage,
286                 this.getClass().getCanonicalName());
287     }
288
289     private void createTransactionRecord(RuntimeContext runtimeContext) {
290         TransactionRecord transactionRecord = new TransactionRecord();
291         transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
292         transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
293         transactionRecord.setStartTime(runtimeContext.getTimeStart());
294         transactionRecord.setEndTime(Instant.now());
295         transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
296         transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
297         transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
298         transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
299         transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
300         transactionRecorder.store(transactionRecord);
301     }
302
303     protected abstract void handleRequest(RuntimeContext runtimeContext) ;
304
305     protected void callWfOperation(RuntimeContext runtimeContext) {
306         int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
307         if (remainingTTL > 0) {
308             if (logger.isDebugEnabled()) {
309                 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
310             }
311
312             RuntimeContext clonedContext = cloneContext(runtimeContext);
313
314             try {
315                 commandExecutor.executeCommand(clonedContext);
316                 if(logger.isTraceEnabled()) {
317                     logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
318                 }
319                 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
320                 if (isMetricEnabled) {
321                     ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
322                 }
323             } catch (APPCException e) {
324                 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
325                 Params params = new Params().addParam("errorMsg", errorMessage);
326                 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
327             }
328
329         } else {
330             fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
331             storeErrorMessageToLog(runtimeContext,
332                     LoggingConstants.TargetNames.APPC,
333                     LoggingConstants.TargetNames.REQUEST_HANDLER,
334                     EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
335                             runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
336                             runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
337                             String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
338         }
339     }
340
341     protected void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
342         runtimeContext.getResponseContext().setStatus(new Status(lcmCommandStatus.getResponseCode(),lcmCommandStatus.getFormattedMessage(params)));
343     }
344
345     /*
346      * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
347      * status code and other - depending on DG status). Other properties should not be a problem
348      */
349     private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
350         RuntimeContext other = new RuntimeContext();
351         other.setRequestContext(runtimeContext.getRequestContext());
352         other.setResponseContext(new ResponseContext());
353         other.getResponseContext().setStatus(new Status(0,""));
354         other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
355         other.setVnfContext(runtimeContext.getVnfContext());
356         other.setRpcName(runtimeContext.getRpcName());
357         other.setTimeStart(runtimeContext.getTimeStart());
358         other.setIsLockAcquired(runtimeContext.isLockAcquired());
359         return other;
360     }
361
362
363     private void clearRequestLogProperties() {
364         try {
365             MDC.remove(MDC_KEY_REQUEST_ID);
366             MDC.remove(MDC_SERVICE_INSTANCE_ID);
367             MDC.remove(MDC_SERVICE_NAME);
368             MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
369             MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
370         } catch (Exception e) {
371             //do nothing
372         }
373     }
374
375     private void removeRequestFromRegistry(CommonHeader commonHeader) {
376         if (logger.isTraceEnabled())
377             logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
378         requestRegistry.removeRequest(
379                 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
380                         commonHeader.getRequestId(),
381                         commonHeader.getSubRequestId()));
382     }
383
384
385     private void setInitialLogProperties(RequestContext requestContext) {
386
387         try {
388             MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
389             if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
390                 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
391             }
392             MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
393             MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
394             try {
395                 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
396                 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
397                 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
398                 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
399                 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
400
401             } catch (Exception e) {
402                 logger.debug(e.getMessage());
403             }
404         } catch (RuntimeException e) {
405             //ignore
406         }
407     }
408
409
410     private int calculateRemainingTTL(CommonHeader commonHeader) {
411         if (logger.isTraceEnabled()) {
412             logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
413         }
414         long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().toEpochMilli());
415         logger.debug("usedTimeInMillis = " + usedTimeInMillis);
416         int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
417         logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
418         Integer inputTTL = this.getInputTTL(commonHeader);
419         logger.debug("inputTTL = " + inputTTL);
420         Integer remainingTTL = inputTTL - usedTimeInSeconds;
421         logger.debug("Remaining TTL = " + remainingTTL);
422         if (logger.isTraceEnabled())
423             logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
424         return remainingTTL;
425     }
426
427     private Integer getInputTTL(CommonHeader header) {
428         if (logger.isTraceEnabled())
429             logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
430         if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
431             String defaultTTLStr = configuration.getProperty("org.onap.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
432             Integer defaultTTL = Integer.parseInt(defaultTTLStr);
433             if (logger.isTraceEnabled())
434                 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
435             return defaultTTL;
436         }
437         if (logger.isTraceEnabled())
438             logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
439
440         return header.getFlags().getTtl();
441     }
442
443     private boolean isValidTTL(String ttl) {
444         if (ttl == null || ttl.length() == 0) {
445             if (logger.isTraceEnabled())
446                 logger.trace("Exiting from getInputTTL with (result = false)");
447             return false;
448         }
449         try {
450             Integer i = Integer.parseInt(ttl);
451             return (i > 0);
452         } catch (NumberFormatException e) {
453             if (logger.isTraceEnabled())
454                 logger.trace("Exiting from getInputTTL with (result = false)");
455             return false;
456         }
457     }
458
459     private Boolean isLoggingEnabled() {
460         String defaultFlagStr = configuration.getProperty("org.onap.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
461         return Boolean.parseBoolean(defaultFlagStr);
462     }
463
464     private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
465         RequestHandlerOutput output = new RequestHandlerOutput();
466         ResponseContext responseContext = new ResponseContext();
467         org.onap.appc.domainmodel.lcm.Status status = new org.onap.appc.domainmodel.lcm.Status(response.getResponseCode(),response.getFormattedMessage(params));
468         responseContext.setStatus(status);
469         output.setResponseContext(responseContext);
470         return output;
471     }
472
473     /**
474      * This method perform operations required before execution of workflow starts. It retrieves next state for current operation from Lifecycle manager and update it in AAI.
475      *
476      * @param vnfId String of VNF ID
477      * @param readOnlyActivity boolean indicator
478      * @param  requestIdentifierString - string contains id uniquely represents the request
479      * @param forceFlag boolean indicator
480      * @throws UnstableVNFException when failed
481      */
482     @Override
483     public abstract void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException ;
484
485     /**
486      * This method perform following operations required after execution of workflow.
487      * It posts asynchronous response to message bus (DMaaP).
488      * Unlock VNF Id
489      * Removes request from request registry.
490      * Generate audit logs.
491      * Adds transaction record to database id if transaction logging is enabled.
492      *
493      * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
494      */
495     @Override
496     public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
497         if (logger.isTraceEnabled()) {
498             logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
499         }
500
501         postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
502         requestRegistry.removeRequest(
503                 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
504                         runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
505                         runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
506
507         storeAuditLogRecord(runtimeContext);
508         if (isLoggingEnabled()) {
509             createTransactionRecord(runtimeContext);
510         }
511     }
512
513     private void storeAuditLogRecord(RuntimeContext runtimeContext) {
514         LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
515                 Instant.now(),
516                 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
517                 runtimeContext.getResponseContext().getStatus().getMessage(),
518                 this.getClass().getCanonicalName());
519     }
520
521     private void storeMetricLogRecord(RuntimeContext runtimeContext) {
522         LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
523                 Instant.now(),
524                 LoggingConstants.TargetNames.APPC,
525                 runtimeContext.getRequestContext().getAction().name(),
526                 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
527                 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
528                 runtimeContext.getResponseContext().getStatus().getMessage(),
529                 this.getClass().getCanonicalName());
530     }
531
532
533
534
535     private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext) {
536         if (logger.isTraceEnabled()) {
537             logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
538         }
539         boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
540         if (!callbackResponse) {
541             logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
542         }
543         if (logger.isTraceEnabled())
544             logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
545     }
546
547     /**
548      * This method perform following operations required if TTL ends when request still waiting in execution queue .
549      * It posts asynchronous response to message bus (DMaaP).
550      * Unlock VNF Id
551      * Removes request from request registry.
552      *
553      * @param runtimeContext AsyncResponse object which contains VNF Id         , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
554      * @param updateAAI      boolean flag which indicate AAI upodate status after request completion.
555      */
556     @Override
557     public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
558         if (logger.isTraceEnabled()) {
559             logger.trace("Entering to onRequestTTLEnd with " +
560                     "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
561                     ", updateAAI = " + ObjectUtils.toString(updateAAI));
562         }
563         logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
564         fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
565         postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
566
567         requestRegistry.removeRequest(
568                 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
569                         runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
570                         runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
571     }
572
573     private void initMetric() {
574         if (logger.isDebugEnabled())
575             logger.debug("Metric getting initialized");
576         MetricService metricService = getMetricservice();
577         metricRegistry = metricService.createRegistry("APPC");
578         DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
579                 dispatchingFunctionCounterBuilder().
580                 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
581                 withAcceptRequestValue(0)
582                 .withRejectRequestValue(0)
583                 .build();
584         if (metricRegistry.register(dispatchingFuntionMetric)) {
585             Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
586             LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
587             LogPublisher[] logPublishers = new LogPublisher[1];
588             logPublishers[0] = logPublisher;
589             PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
590                     scheduledPolicyBuilder().withPublishers(logPublishers).
591                     withMetrics(metrics).
592                     build();
593             if (logger.isDebugEnabled())
594                 logger.debug("Policy getting initialized");
595             manuallyScheduledPublishingPolicy.init();
596             if (logger.isDebugEnabled())
597                 logger.debug("Metric initialized");
598         }
599     }
600
601
602     private MetricService getMetricservice() {
603         BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
604         ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
605         if (sref != null) {
606             logger.info("Metric Service from bundlecontext");
607             return (MetricService) bctx.getService(sref);
608         } else {
609             logger.info("Metric Service error from bundlecontext");
610             logger.warn("Cannot find service reference for org.onap.appc.metricservice.MetricService");
611             return null;
612         }
613     }
614
615     /**
616      * This method returns the count of in progress requests
617      * * @return in progress requests count
618      */
619     @Override
620     public int getInprogressRequestCount() {
621         if (logger.isTraceEnabled()) {
622             logger.trace("Entering to getInprogressRequestCount");
623         }
624         return requestRegistry.getRegisteredRequestCount();
625     }
626 }