2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  19  * ============LICENSE_END=========================================================
 
  22 package org.openecomp.appc.requesthandler.impl;
 
  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;
 
  74 import static com.att.eelf.configuration.Configuration.*;
 
  76 import java.net.InetAddress;
 
  77 import java.util.Date;
 
  78 import java.util.HashMap;
 
  80 import java.util.Properties;
 
  83  * This class provides application logic for the Request/Response Handler Component.
 
  86 public class RequestHandlerImpl implements RequestHandler {
 
  89      * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
 
  91     private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout";
 
  93     private CommandExecutor commandExecutor;
 
  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;
 
 105     private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
 
 107     public void setAaiService(AAIService aaiService) {
 
 108         this.aaiService = aaiService;
 
 111     public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
 
 112         this.transactionRecorder = transactionRecorder;
 
 115     public void setLockManager(LockManager lockManager) {
 
 116         this.lockManager = lockManager;
 
 119     public void setRequestValidator(RequestValidator requestValidator) {
 
 120         this.requestValidator = requestValidator;
 
 123     public void setMessageAdapter(MessageAdapter messageAdapter) {
 
 124         this.messageAdapter = messageAdapter;
 
 127     private static final Configuration configuration = ConfigurationFactory.getConfiguration();
 
 129     public void setWorkingStateManager(WorkingStateManager workingStateManager) {
 
 130         this.workingStateManager = workingStateManager;
 
 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"));
 
 141         if (isMetricEnabled) {
 
 146     public void setCommandExecutor(CommandExecutor commandExecutor) {
 
 147         this.commandExecutor = commandExecutor;
 
 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
 
 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.
 
 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());
 
 172         RuntimeContext runtimeContext = new RuntimeContext();
 
 173         runtimeContext.setRequestContext(input.getRequestContext());
 
 174         runtimeContext.setTimeStart(startTime);
 
 175         runtimeContext.setRpcName(input.getRpcName());
 
 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());
 
 184         vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
 
 188             requestValidator.validateRequest(runtimeContext);
 
 190             handleRequest(runtimeContext);
 
 192             final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
 
 193             if (statusCode % 100 == 2 || statusCode % 100 == 3) {
 
 194                 createTransactionRecord(runtimeContext);
 
 196             output = new RequestHandlerOutput();
 
 197             output.setResponseContext(runtimeContext.getResponseContext());
 
 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,
 
 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,
 
 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);
 
 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()));
 
 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();
 
 265                     removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
 
 268                 storeAuditLogRecord(runtimeContext);
 
 269                 storeMetricLogRecord(runtimeContext);
 
 270                 clearRequestLogProperties();
 
 273         if (logger.isTraceEnabled()) {
 
 274             logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
 
 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()) : "",
 
 287                 this.getClass().getCanonicalName());
 
 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);
 
 304     private void handleRequest(RuntimeContext runtimeContext) {
 
 306         switch (runtimeContext.getRequestContext().getAction()) {
 
 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()));
 
 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);
 
 335                 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
 
 336                 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
 
 337                 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
 
 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);
 
 348                     if (runtimeContext.isLockAcquired()) {
 
 349                         final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
 
 350                         if (statusCode % 100 == 2 || statusCode % 100 == 3) {
 
 352                                 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
 
 353                                 //TODO add logger call
 
 354                             } catch (LockException e) {
 
 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);
 
 371             RuntimeContext clonedContext = cloneContext(runtimeContext);
 
 373             CommandExecutorInput commandExecutorInput = new CommandExecutorInput();
 
 374             commandExecutorInput.setRuntimeContext(clonedContext);
 
 375             commandExecutorInput.setTtl(remainingTTL);
 
 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()));
 
 382                 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
 
 383                 if (isMetricEnabled) {
 
 384                     ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
 
 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);
 
 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())));
 
 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));
 
 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
 
 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());
 
 427     private void clearRequestLogProperties() {
 
 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) {
 
 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()));
 
 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);
 
 453             logger.info("Lock acquired for vnfID = " + vnfID);
 
 455             logger.info("vnfID = " + vnfID + " was already locked");
 
 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);
 
 465     private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
 
 468                 releaseVNFLock(vnfId, requestId);
 
 469             } catch (LockException e) {
 
 470                 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
 
 474         } else if (resetLockTimeout) {
 
 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);
 
 484     private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
 
 485         lockManager.releaseLock(vnfId, transactionId);
 
 486         logger.info("Lock released for vnfID = " + vnfId);
 
 489     private void setInitialLogProperties(RequestContext requestContext) {
 
 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());
 
 496             MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
 
 497             MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
 
 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());
 
 505             } catch (Exception e) {
 
 506                 logger.debug(e.getMessage());
 
 508         } catch (RuntimeException e) {
 
 514     private int calculateRemainingTTL(CommonHeader commonHeader) {
 
 515         if (logger.isTraceEnabled()) {
 
 516             logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
 
 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) + ")");
 
 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) + ")");
 
 541         if (logger.isTraceEnabled())
 
 542             logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
 
 544         return header.getFlags().getTtl();
 
 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)");
 
 554             Integer i = Integer.parseInt(ttl);
 
 556         } catch (NumberFormatException e) {
 
 557             if (logger.isTraceEnabled())
 
 558                 logger.trace("Exiting from getInputTTL with (result = false)");
 
 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);
 
 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);
 
 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.
 
 583      * @return true in case AAI updates are successful. false for any error or exception.
 
 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);
 
 591             boolean updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
 
 593                 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
 
 595         } catch (Exception e) {
 
 596             logger.error("Error updating working state for vnf " + vnfId + e);
 
 597             throw new RuntimeException(e);
 
 600         if (logger.isTraceEnabled())
 
 601             logger.trace("Exiting from onRequestExecutionStart ");
 
 605      * This method perform following operations required after execution of workflow.
 
 606      * It posts asynchronous response to message bus (DMaaP).
 
 608      * Removes request from request registry.
 
 609      * Generate audit logs.
 
 610      * Adds transaction record to database id if transaction logging is enabled.
 
 612      * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
 
 615     public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
 
 616         if (logger.isTraceEnabled()) {
 
 617             logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
 
 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();
 
 628         VNFWorkingState workingState;
 
 629         if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
 
 630             workingState = VNFWorkingState.STABLE;
 
 632             workingState = VNFWorkingState.UNKNOWN;
 
 635         UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
 
 636                 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
 
 637                 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
 
 639         String requestIdentifierString = requestIdentifier.toIdentifierString();
 
 640         workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
 
 643         storeAuditLogRecord(runtimeContext);
 
 645         if (isLoggingEnabled()) {
 
 646             createTransactionRecord(runtimeContext);
 
 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());
 
 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());
 
 669     private boolean isReadOnlyAction(VNFOperation action) {
 
 670         return VNFOperation.Sync == action
 
 671                 || VNFOperation.Audit == action;
 
 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));
 
 680         /*boolean updated = updateAsyncResponseStatus(responseContext, isTTLEnd, aaiUpdateSuccess);
 
 682         boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
 
 683         if (!callbackResponse) {
 
 684             logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
 
 686         if (logger.isTraceEnabled())
 
 687             logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
 
 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());
 
 702                 asyncResponse.getStatus().setCode(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseCode());
 
 703                 asyncResponse.getStatus().setMessage(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
 
 706         if (logger.isTraceEnabled())
 
 707             logger.trace("Exiting from updateAsyncResponseStatus with (asyncResponse = "+ ObjectUtils.toString(asyncResponse)+")");
 
 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).
 
 716      * Removes request from request registry.
 
 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.
 
 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));
 
 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()));
 
 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));
 
 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);
 
 753             logger.info("AAIResponse: " + response.toString());
 
 754         } catch (SvcLogicException e) {
 
 755             logger.error("Error in getVnfdata " + e);
 
 756             throw new RuntimeException(e);
 
 758         if (logger.isTraceEnabled()) {
 
 759             logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
 
 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));
 
 772         String key = "vnf-id = '" + vnf_id + "'";
 
 773         Map<String, String> data = new HashMap<>();
 
 774         data.put("orchestration-status", status);
 
 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);
 
 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) + ")");
 
 788         } catch (SvcLogicException e) {
 
 789             logger.error("Error in postVnfdata " + e);
 
 790             throw new RuntimeException(e);
 
 792         if (logger.isTraceEnabled()) {
 
 793             logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
 
 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)
 
 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).
 
 818             if (logger.isDebugEnabled())
 
 819                 logger.debug("Policy getting initialized");
 
 820             manuallyScheduledPublishingPolicy.init();
 
 821             if (logger.isDebugEnabled())
 
 822                 logger.debug("Metric initialized");
 
 827     private MetricService getMetricservice() {
 
 828         BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
 
 829         ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
 
 831             logger.info("Metric Service from bundlecontext");
 
 832             return (MetricService) bctx.getService(sref);
 
 834             logger.info("Metric Service error from bundlecontext");
 
 835             logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");