Change nexus values to properties
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / openecomp / appc / requesthandler / impl / RequestHandlerImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : APP-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                              reserved.
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
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
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  */
21
22 package org.openecomp.appc.requesthandler.impl;
23
24 import org.apache.commons.lang.ObjectUtils;
25 import org.openecomp.appc.common.constant.Constants;
26 import org.openecomp.appc.configuration.Configuration;
27 import org.openecomp.appc.configuration.ConfigurationFactory;
28 import org.openecomp.appc.domainmodel.lcm.*;
29 import org.openecomp.appc.exceptions.APPCException;
30 import org.openecomp.appc.executor.CommandExecutor;
31 import org.openecomp.appc.executor.UnstableVNFException;
32 import org.openecomp.appc.executor.objects.CommandExecutorInput;
33 import org.openecomp.appc.executor.objects.LCMCommandStatus;
34 import org.openecomp.appc.executor.objects.Params;
35 import org.openecomp.appc.executor.objects.UniqueRequestIdentifier;
36 import org.openecomp.appc.i18n.Msg;
37 import org.openecomp.appc.lifecyclemanager.objects.LifecycleException;
38 import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException;
39 import org.openecomp.appc.lockmanager.api.LockException;
40 import org.openecomp.appc.lockmanager.api.LockManager;
41 import org.openecomp.appc.logging.LoggingConstants;
42 import org.openecomp.appc.logging.LoggingUtils;
43 import org.openecomp.appc.messageadapter.MessageAdapter;
44 import org.openecomp.appc.messageadapter.impl.MessageAdapterDmaapImpl;
45 import org.openecomp.appc.metricservice.MetricRegistry;
46 import org.openecomp.appc.metricservice.MetricService;
47 import org.openecomp.appc.metricservice.metric.DispatchingFuntionMetric;
48 import org.openecomp.appc.metricservice.metric.Metric;
49 import org.openecomp.appc.metricservice.metric.MetricType;
50 import org.openecomp.appc.metricservice.policy.PublishingPolicy;
51 import org.openecomp.appc.metricservice.publisher.LogPublisher;
52 import org.openecomp.appc.requesthandler.RequestHandler;
53 import org.openecomp.appc.requesthandler.exceptions.*;
54 import org.openecomp.appc.requesthandler.helper.RequestRegistry;
55 import org.openecomp.appc.requesthandler.helper.RequestValidator;
56 import org.openecomp.appc.requesthandler.objects.RequestHandlerInput;
57 import org.openecomp.appc.requesthandler.objects.RequestHandlerOutput;
58 import org.openecomp.appc.transactionrecorder.TransactionRecorder;
59 import org.openecomp.appc.transactionrecorder.objects.TransactionRecord;
60 import org.openecomp.appc.workingstatemanager.WorkingStateManager;
61 import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
62 import com.att.eelf.configuration.EELFLogger;
63 import com.att.eelf.configuration.EELFManager;
64 import com.att.eelf.i18n.EELFResourceManager;
65 import org.openecomp.sdnc.sli.SvcLogicContext;
66 import org.openecomp.sdnc.sli.SvcLogicException;
67 import org.openecomp.sdnc.sli.SvcLogicResource.QueryStatus;
68 import org.openecomp.sdnc.sli.aai.AAIService;
69 import org.osgi.framework.BundleContext;
70 import org.osgi.framework.FrameworkUtil;
71 import org.osgi.framework.ServiceReference;
72 import org.slf4j.MDC;
73
74 import static com.att.eelf.configuration.Configuration.*;
75
76 import java.net.InetAddress;
77 import java.util.Date;
78 import java.util.HashMap;
79 import java.util.Map;
80 import java.util.Properties;
81
82 /**
83  * This class provides application logic for the Request/Response Handler Component.
84  *
85  */
86 public class RequestHandlerImpl implements RequestHandler {
87
88     /**
89      * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
90      */
91     private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout";
92
93     private CommandExecutor commandExecutor;
94
95     private TransactionRecorder transactionRecorder;
96     private MessageAdapter messageAdapter;
97     private RequestValidator requestValidator;
98     private static MetricRegistry metricRegistry;
99     private boolean isMetricEnabled = false;
100     private RequestRegistry requestRegistry;
101     private LockManager lockManager;
102     private WorkingStateManager workingStateManager;
103     private AAIService aaiService;
104
105     private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
106
107     public void setAaiService(AAIService aaiService) {
108         this.aaiService = aaiService;
109     }
110
111     public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
112         this.transactionRecorder = transactionRecorder;
113     }
114
115     public void setLockManager(LockManager lockManager) {
116         this.lockManager = lockManager;
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     private static final Configuration configuration = ConfigurationFactory.getConfiguration();
128
129     public void setWorkingStateManager(WorkingStateManager workingStateManager) {
130         this.workingStateManager = workingStateManager;
131     }
132
133     public RequestHandlerImpl() {
134         requestRegistry = new RequestRegistry();
135         messageAdapter = new MessageAdapterDmaapImpl();
136         messageAdapter.init();
137         Properties properties = configuration.getProperties();
138         if (properties != null && properties.getProperty("metric.enabled") != null) {
139             isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
140         }
141         if (isMetricEnabled) {
142             initMetric();
143         }
144     }
145
146     public void setCommandExecutor(CommandExecutor commandExecutor) {
147         this.commandExecutor = commandExecutor;
148     }
149
150
151     /**
152      * It receives requests from the north-bound REST API (Communication) Layer and
153      * performs following validations.
154      * 1. VNF exists in A&AI for the given targetID (VnfID)
155      * 2. For the current VNF  Orchestration Status, the command can be executed
156      * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
157      * If any of the validation fails, it returns appropriate response
158      *
159      * @param input RequestHandlerInput object which contains request header and  other request parameters like command , target Id , payload etc.
160      * @return response for request as enum with Return code and message.
161      */
162     @Override
163     public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
164         if (logger.isTraceEnabled())
165             logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
166         Params params = null;
167         String vnfId = null, vnfType = null, errorMessage = null;
168         Date startTime = new Date(System.currentTimeMillis());
169         RequestHandlerOutput output = null;
170         setInitialLogProperties(input.getRequestContext());
171
172         RuntimeContext runtimeContext = new RuntimeContext();
173         runtimeContext.setRequestContext(input.getRequestContext());
174         runtimeContext.setTimeStart(startTime);
175         runtimeContext.setRpcName(input.getRpcName());
176
177         final ResponseContext responseContext = new ResponseContext();
178         responseContext.setStatus(new Status());
179         responseContext.setAdditionalContext(new HashMap<String, String>(4));
180         responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
181         runtimeContext.setResponseContext(responseContext);
182         runtimeContext.getResponseContext().setStatus(new Status());
183
184         vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
185
186         try {
187
188             requestValidator.validateRequest(runtimeContext);
189
190             handleRequest(runtimeContext);
191
192             final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
193             if (statusCode % 100 == 2 || statusCode % 100 == 3) {
194                 createTransactionRecord(runtimeContext);
195             }
196             output = new RequestHandlerOutput();
197             output.setResponseContext(runtimeContext.getResponseContext());
198
199         } catch (VNFNotFoundException e) {
200             errorMessage = e.getMessage();
201             String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
202             storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
203             params = new Params().addParam("vnfId", vnfId);
204             output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
205         } catch (NoTransitionDefinedException e) {
206             errorMessage = e.getMessage();
207             String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
208             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
209             output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
210             storeErrorMessageToLog(runtimeContext,
211                     LoggingConstants.TargetNames.APPC,
212                     LoggingConstants.TargetNames.STATE_MACHINE,
213                     logMessage);
214         } catch (LifecycleException e) {
215             errorMessage = e.getMessage();
216             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
217             output = buildRequestHandlerOutput(LCMCommandStatus.ACTION_NOT_SUPPORTED, params);
218         } catch (UnstableVNFException e) {
219             errorMessage = e.getMessage();
220             params = new Params().addParam("vnfId", vnfId);
221             output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
222         } catch (WorkflowNotFoundException e) {
223             errorMessage = e.getMessage();
224             String vnfTypeVersion = e.vnfTypeVersion;
225             params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
226             output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
227         } catch (DGWorkflowNotFoundException e) {
228             errorMessage = e.getMessage();
229             String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
230             storeErrorMessageToLog(runtimeContext,
231                     LoggingConstants.TargetNames.APPC,
232                     LoggingConstants.TargetNames.WORKFLOW_MANAGER,
233                     logMessage);
234             params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
235                     .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
236             output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
237         } catch (RequestExpiredException e) {
238             errorMessage = e.getMessage();
239             params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
240             output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
241         } catch (InvalidInputException e) {
242             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
243             params = new Params().addParam("errorMsg", errorMessage);
244             output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
245         } catch (DuplicateRequestException e) {
246             errorMessage = e.getMessage();
247             output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
248         } catch (Exception e) {
249             storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
250             errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
251             params = new Params().addParam("errorMsg", errorMessage);
252             output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
253         } finally {
254             try {
255                 if (logger.isDebugEnabled() && errorMessage != null)
256                     logger.debug("error occurred in handleRequest " + errorMessage);
257                 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
258                 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode():  " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
259
260                 runtimeContext.setResponseContext(output.getResponseContext());
261                 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
262                     if (isMetricEnabled) {
263                         ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
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     private 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(new Date(System.currentTimeMillis()));
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     private void handleRequest(RuntimeContext runtimeContext) {
305
306         switch (runtimeContext.getRequestContext().getAction()) {
307             case Lock:
308                 try {
309                     lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
310                     fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
311                 } catch (LockException e) {
312                     Params params = new Params().addParam("errorMsg", e.getMessage());
313                     fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
314                     storeErrorMessageToLog(runtimeContext,
315                             LoggingConstants.TargetNames.APPC,
316                             LoggingConstants.TargetNames.LOCK_MANAGER,
317                             EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
318                 }
319
320                 break;
321
322             case Unlock:
323                 try {
324                     releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
325                     fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
326                 } catch (LockException e) {
327                     //TODO add proper error code and message
328                     //  logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
329                     Params params = new Params().addParam("errorMsg", e.getMessage());
330                     fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
331                 }
332                 break;
333
334             case CheckLock:
335                 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
336                 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
337                 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
338                 break;
339             default:
340                 try {
341                     boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
342                     runtimeContext.setIsLockAcquired(lockAcquired);
343                     callWfOperation(runtimeContext);
344                 } catch (LockException e) {
345                     Params params = new Params().addParam("errorMsg", e.getMessage());
346                     fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
347                 } finally {
348                     if (runtimeContext.isLockAcquired()) {
349                         final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
350                         if (statusCode % 100 == 2 || statusCode % 100 == 3) {
351                             try {
352                                 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
353                                 //TODO add logger call
354                             } catch (LockException e) {
355                                 //ignore
356                             }
357                         }
358                     }
359                 }
360         }
361
362     }
363
364     private void callWfOperation(RuntimeContext runtimeContext) {
365         int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
366         if (remainingTTL > 0) {
367             if (logger.isDebugEnabled()) {
368                 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
369             }
370
371             RuntimeContext clonedContext = cloneContext(runtimeContext);
372
373             CommandExecutorInput commandExecutorInput = new CommandExecutorInput();
374             commandExecutorInput.setRuntimeContext(clonedContext);
375             commandExecutorInput.setTtl(remainingTTL);
376
377             try {
378                 commandExecutor.executeCommand(commandExecutorInput);
379                 if(logger.isTraceEnabled()) {
380                     logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
381                 }
382                 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
383                 if (isMetricEnabled) {
384                     ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
385                 }
386             } catch (APPCException e) {
387                 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
388                 Params params = new Params().addParam("errorMsg", errorMessage);
389                 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
390             }
391
392         } else {
393             fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
394             storeErrorMessageToLog(runtimeContext,
395                     LoggingConstants.TargetNames.APPC,
396                     LoggingConstants.TargetNames.REQUEST_HANDLER,
397                     EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
398                             runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
399                             runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
400                             String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
401         }
402     }
403
404     private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
405         runtimeContext.getResponseContext().getStatus().setCode(lcmCommandStatus.getResponseCode());
406         runtimeContext.getResponseContext().getStatus().setMessage(lcmCommandStatus.getFormattedMessage(params));
407     }
408
409     /*
410      * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
411      * status code and other - depending on DG status). Other properties should not be a problem
412      */
413     private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
414         RuntimeContext other = new RuntimeContext();
415         other.setRequestContext(runtimeContext.getRequestContext());
416         other.setResponseContext(new ResponseContext());
417         other.getResponseContext().setStatus(new Status());
418         other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
419         other.setVnfContext(runtimeContext.getVnfContext());
420         other.setRpcName(runtimeContext.getRpcName());
421         other.setTimeStart(runtimeContext.getTimeStart());
422         other.setIsLockAcquired(runtimeContext.isLockAcquired());
423         return other;
424     }
425
426
427     private void clearRequestLogProperties() {
428         try {
429             MDC.remove(MDC_KEY_REQUEST_ID);
430             MDC.remove(MDC_SERVICE_INSTANCE_ID);
431             MDC.remove(MDC_SERVICE_NAME);
432             MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
433             MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
434         } catch (Exception e) {
435
436         }
437     }
438
439     private void removeRequestFromRegistry(CommonHeader commonHeader) {
440         if (logger.isTraceEnabled())
441             logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
442         requestRegistry.removeRequest(
443                 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
444                         commonHeader.getRequestId(),
445                         commonHeader.getSubRequestId()));
446     }
447
448     private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
449         if (logger.isTraceEnabled())
450             logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
451         boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
452         if (lockAcquired) {
453             logger.info("Lock acquired for vnfID = " + vnfID);
454         } else {
455             logger.info("vnfID = " + vnfID + " was already locked");
456         }
457         return lockAcquired;
458     }
459
460     private void lockWithTimeout(String vnfId, String requestId) throws LockException {
461         long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
462         acquireVNFLock(vnfId, requestId, timeout);
463     }
464
465     private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
466         if (lockAcquired) {
467             try {
468                 releaseVNFLock(vnfId, requestId);
469             } catch (LockException e) {
470                 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
471
472
473             }
474         } else if (resetLockTimeout) {
475             try {
476                 // reset timeout to previous value
477                 lockWithTimeout(vnfId, requestId);
478             } catch (LockException e) {
479                 logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
480             }
481         }
482     }
483
484     private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
485         lockManager.releaseLock(vnfId, transactionId);
486         logger.info("Lock released for vnfID = " + vnfId);
487     }
488
489     private void setInitialLogProperties(RequestContext requestContext) {
490
491         try {
492             MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
493             if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
494                 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
495             }
496             MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
497             MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
498             try {
499                 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
500                 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
501                 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
502                 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
503                 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
504
505             } catch (Exception e) {
506                 logger.debug(e.getMessage());
507             }
508         } catch (RuntimeException e) {
509             //ignore
510         }
511     }
512
513
514     private int calculateRemainingTTL(CommonHeader commonHeader) {
515         if (logger.isTraceEnabled()) {
516             logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
517         }
518         long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().getTime());
519         logger.debug("usedTimeInMillis = " + usedTimeInMillis);
520         int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
521         logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
522         Integer inputTTL = this.getInputTTL(commonHeader);
523         logger.debug("inputTTL = " + inputTTL);
524         Integer remainingTTL = inputTTL - usedTimeInSeconds;
525         logger.debug("Remaining TTL = " + remainingTTL);
526         if (logger.isTraceEnabled())
527             logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
528         return remainingTTL;
529     }
530
531     private Integer getInputTTL(CommonHeader header) {
532         if (logger.isTraceEnabled())
533             logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
534         if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
535             String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
536             Integer defaultTTL = Integer.parseInt(defaultTTLStr);
537             if (logger.isTraceEnabled())
538                 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
539             return defaultTTL;
540         }
541         if (logger.isTraceEnabled())
542             logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
543
544         return header.getFlags().getTtl();
545     }
546
547     private boolean isValidTTL(String ttl) {
548         if (ttl == null || ttl.length() == 0) {
549             if (logger.isTraceEnabled())
550                 logger.trace("Exiting from getInputTTL with (result = false)");
551             return false;
552         }
553         try {
554             Integer i = Integer.parseInt(ttl);
555             return (i > 0);
556         } catch (NumberFormatException e) {
557             if (logger.isTraceEnabled())
558                 logger.trace("Exiting from getInputTTL with (result = false)");
559             return false;
560         }
561     }
562
563     private Boolean isLoggingEnabled() {
564         String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
565         Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr);
566         return defaultFlag;
567     }
568
569     private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
570         RequestHandlerOutput output = new RequestHandlerOutput();
571         ResponseContext responseContext = new ResponseContext();
572         org.openecomp.appc.domainmodel.lcm.Status status = new org.openecomp.appc.domainmodel.lcm.Status();
573         status.setCode(response.getResponseCode());
574         status.setMessage(response.getFormattedMessage(params));
575         responseContext.setStatus(status);
576         output.setResponseContext(responseContext);
577         return output;
578     }
579
580     /**
581      * 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.
582      *
583      * @return true in case AAI updates are successful. false for any error or exception.
584      */
585     @Override
586     public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
587         if (logger.isTraceEnabled()) {
588             logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
589         }
590         try {
591             boolean updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
592             if (!updated) {
593                 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
594             }
595         } catch (Exception e) {
596             logger.error("Error updating working state for vnf " + vnfId + e);
597             throw new RuntimeException(e);
598         }
599
600         if (logger.isTraceEnabled())
601             logger.trace("Exiting from onRequestExecutionStart ");
602     }
603
604     /**
605      * This method perform following operations required after execution of workflow.
606      * It posts asynchronous response to message bus (DMaaP).
607      * Unlock VNF Id
608      * Removes request from request registry.
609      * Generate audit logs.
610      * Adds transaction record to database id if transaction logging is enabled.
611      *
612      * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
613      */
614     @Override
615     public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
616         if (logger.isTraceEnabled()) {
617             logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
618         }
619
620         postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
621         requestRegistry.removeRequest(
622                 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
623                         runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
624                         runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
625         resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
626         Status status = runtimeContext.getResponseContext().getStatus();
627
628         VNFWorkingState workingState;
629         if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
630             workingState = VNFWorkingState.STABLE;
631         } else {
632             workingState = VNFWorkingState.UNKNOWN;
633         }
634
635         UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
636                 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
637                 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
638
639         String requestIdentifierString = requestIdentifier.toIdentifierString();
640         workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
641
642
643         storeAuditLogRecord(runtimeContext);
644
645         if (isLoggingEnabled()) {
646             createTransactionRecord(runtimeContext);
647         }
648     }
649
650     private void storeAuditLogRecord(RuntimeContext runtimeContext) {
651         LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
652                 new Date(System.currentTimeMillis()),
653                 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
654                 runtimeContext.getResponseContext().getStatus().getMessage(),
655                 this.getClass().getCanonicalName());
656     }
657
658     private void storeMetricLogRecord(RuntimeContext runtimeContext) {
659         LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
660                 new Date(System.currentTimeMillis()),
661                 LoggingConstants.TargetNames.APPC,
662                 runtimeContext.getRequestContext().getAction().name(),
663                 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
664                 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
665                 runtimeContext.getResponseContext().getStatus().getMessage(),
666                 this.getClass().getCanonicalName());
667     }
668
669     private boolean isReadOnlyAction(VNFOperation action) {
670         return VNFOperation.Sync == action
671                 || VNFOperation.Audit == action;
672     }
673
674
675     //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse
676     private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) {
677         if (logger.isTraceEnabled()) {
678             logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
679         }
680         /*boolean updated = updateAsyncResponseStatus(responseContext, isTTLEnd, aaiUpdateSuccess);
681          */
682         boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
683         if (!callbackResponse) {
684             logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
685         }
686         if (logger.isTraceEnabled())
687             logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
688     }
689
690     //returns true if asyncResponse was modified
691     /*    private boolean updateAsyncResponseStatus(ResponseContext asyncResponse, boolean isTTLEnd, boolean aaiUpdateSuccess) {
692         boolean updated = false;
693         if (logger.isTraceEnabled())
694             logger.trace("Entering to updateAsyncResponseStatus with AsyncResponse = "+ObjectUtils.toString(asyncResponse)+ ", isTTLEnd = "+ ObjectUtils.toString(isTTLEnd)+ ", aaiUpdateSuccess = "+ ObjectUtils.toString(aaiUpdateSuccess));
695         if(!aaiUpdateSuccess){
696                 if (asyncResponse.getStatus().getCode() == 0 || asyncResponse.getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()) {
697                     asyncResponse.getStatus().setCode(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseCode());
698                     asyncResponse.getStatus().setMessage(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseMessage());
699                 updated = true;
700             }
701         }else if(isTTLEnd){
702                 asyncResponse.getStatus().setCode(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseCode());
703                 asyncResponse.getStatus().setMessage(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
704             updated = true;
705         }
706         if (logger.isTraceEnabled())
707             logger.trace("Exiting from updateAsyncResponseStatus with (asyncResponse = "+ ObjectUtils.toString(asyncResponse)+")");
708         return updated;
709     }*/
710
711
712     /**
713      * This method perform following operations required if TTL ends when request still waiting in execution queue .
714      * It posts asynchronous response to message bus (DMaaP).
715      * Unlock VNF Id
716      * Removes request from request registry.
717      *
718      * @param runtimeContext AsyncResponse object which contains VNF Id         , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
719      * @param updateAAI      boolean flag which indicate AAI upodate status after request completion.
720      */
721     @Override
722     public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
723         if (logger.isTraceEnabled()) {
724             logger.trace("Entering to onRequestTTLEnd with " +
725                     "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
726                     ", updateAAI = " + ObjectUtils.toString(updateAAI));
727         }
728         logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
729         fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
730         postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
731         resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
732         requestRegistry.removeRequest(
733                 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
734                         runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
735                         runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
736     }
737
738     private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
739         String key = "vnf-id = '" + vnf_id + "'";
740         if (logger.isTraceEnabled()) {
741             logger.trace("Entering to getVnfdata with " +
742                     "vnfId = " + vnf_id +
743                     ", prefix = " + prefix +
744                     ", SvcLogicContex = " + ObjectUtils.toString(ctx));
745         }
746         try {
747             QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx);
748             if (QueryStatus.NOT_FOUND.equals(response)) {
749                 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
750             } else if (QueryStatus.FAILURE.equals(response)) {
751                 throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id);
752             }
753             logger.info("AAIResponse: " + response.toString());
754         } catch (SvcLogicException e) {
755             logger.error("Error in getVnfdata " + e);
756             throw new RuntimeException(e);
757         }
758         if (logger.isTraceEnabled()) {
759             logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
760         }
761         return ctx;
762     }
763
764     private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
765         if (logger.isTraceEnabled()) {
766             logger.trace("Entering to postVnfdata with " +
767                     "vnfId = " + vnf_id +
768                     ", status = " + status +
769                     ", prefix = " + prefix +
770                     ", SvcLogicContext = " + ObjectUtils.toString(ctx));
771         }
772         String key = "vnf-id = '" + vnf_id + "'";
773         Map<String, String> data = new HashMap<>();
774         data.put("orchestration-status", status);
775         try {
776             QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx);
777             if (QueryStatus.NOT_FOUND.equals(response)) {
778                 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
779             }
780             logger.info("AAIResponse: " + response.toString());
781             if (response.toString().equals("SUCCESS")) {
782                 if (logger.isTraceEnabled()) {
783                     logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")");
784                 }
785                 return true;
786             }
787
788         } catch (SvcLogicException e) {
789             logger.error("Error in postVnfdata " + e);
790             throw new RuntimeException(e);
791         }
792         if (logger.isTraceEnabled()) {
793             logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
794         }
795         return false;
796     }
797
798     private void initMetric() {
799         if (logger.isDebugEnabled())
800             logger.debug("Metric getting initialized");
801         MetricService metricService = getMetricservice();
802         metricRegistry = metricService.createRegistry("APPC");
803         DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
804                 dispatchingFunctionCounterBuilder().
805                 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
806                 withAcceptRequestValue(0)
807                 .withRejectRequestValue(0)
808                 .build();
809         if (metricRegistry.register(dispatchingFuntionMetric)) {
810             Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
811             LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
812             LogPublisher[] logPublishers = new LogPublisher[1];
813             logPublishers[0] = logPublisher;
814             PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
815                     scheduledPolicyBuilder().withPublishers(logPublishers).
816                     withMetrics(metrics).
817                     build();
818             if (logger.isDebugEnabled())
819                 logger.debug("Policy getting initialized");
820             manuallyScheduledPublishingPolicy.init();
821             if (logger.isDebugEnabled())
822                 logger.debug("Metric initialized");
823         }
824     }
825
826
827     private MetricService getMetricservice() {
828         BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
829         ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
830         if (sref != null) {
831             logger.info("Metric Service from bundlecontext");
832             return (MetricService) bctx.getService(sref);
833         } else {
834             logger.info("Metric Service error from bundlecontext");
835             logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");
836             return null;
837         }
838     }
839 }