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