Include impacted changes for APPC-346,APPC-348
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / onap / appc / requesthandler / impl / RequestHandlerImpl.java
index 1f07b27..8dec8a4 100644 (file)
@@ -27,24 +27,22 @@ package org.onap.appc.requesthandler.impl;
 import com.att.eelf.configuration.EELFLogger;
 import com.att.eelf.configuration.EELFManager;
 import com.att.eelf.i18n.EELFResourceManager;
+import org.apache.commons.lang.ObjectUtils;
+import org.onap.appc.domainmodel.lcm.*;
+import org.onap.appc.exceptions.APPCException;
+import org.onap.appc.executor.CommandExecutor;
+import org.onap.appc.executor.objects.CommandExecutorInput;
+import org.onap.appc.metricservice.metric.DispatchingFuntionMetric;
 import org.onap.appc.requesthandler.constant.Constants;
-import org.onap.appc.domainmodel.lcm.RuntimeContext;
-import org.onap.appc.domainmodel.lcm.Status;
-import org.onap.appc.domainmodel.lcm.VNFOperation;
-import org.onap.appc.executor.UnstableVNFException;
 import org.onap.appc.executor.objects.LCMCommandStatus;
 import org.onap.appc.executor.objects.Params;
-import org.onap.appc.executor.objects.UniqueRequestIdentifier;
 import org.onap.appc.i18n.Msg;
 import org.onap.appc.lockmanager.api.LockException;
 import org.onap.appc.lockmanager.api.LockManager;
 import org.onap.appc.logging.LoggingConstants;
-import org.onap.appc.workingstatemanager.WorkingStateManager;
-import org.onap.appc.workingstatemanager.objects.VNFWorkingState;
 
 /**
  * This class provides application logic for the Request/Response Handler Component.
- *
  */
 public class RequestHandlerImpl extends AbstractRequestHandlerImpl {
 
@@ -53,30 +51,37 @@ public class RequestHandlerImpl extends AbstractRequestHandlerImpl {
      */
     private static final String PROP_IDLE_TIMEOUT = "org.onap.appc.lock.idleTimeout";
 
+    private final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
+
     private LockManager lockManager;
+    private CommandExecutor commandExecutor;
+    private boolean isMetricEnabled = false;
 
-    private WorkingStateManager workingStateManager;
+    public RequestHandlerImpl() {
+        super();
+    }
 
     public void setLockManager(LockManager lockManager) {
         this.lockManager = lockManager;
     }
 
-    public void setWorkingStateManager(WorkingStateManager workingStateManager) {
-        this.workingStateManager = workingStateManager;
+    public void setCommandExecutor(CommandExecutor commandExecutor) {
+        this.commandExecutor = commandExecutor;
     }
 
-    private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
-
-    protected void handleRequest(RuntimeContext runtimeContext) {
+    public void handleRequest(RuntimeContext runtimeContext) {
 
         switch (runtimeContext.getRequestContext().getAction()) {
             case Lock:
                 try {
-                    lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
+                    long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
+                    boolean lockAcquired = lockManager.acquireLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), timeout);
+                    logger.info(String.format(lockAcquired ? "Lock acquired for vnfID = %s" : " VnfId  : %s was already locked.", runtimeContext.getVnfContext().getId()));
                     fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
                 } catch (LockException e) {
+                    logger.error("Error during Lock operation: " + e.getMessage(), e);
                     Params params = new Params().addParam("errorMsg", e.getMessage());
-                    fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
+                    fillStatus(runtimeContext, LCMCommandStatus.LOCKED_VNF_ID, params);
                     storeErrorMessageToLog(runtimeContext,
                             LoggingConstants.TargetNames.APPC,
                             LoggingConstants.TargetNames.LOCK_MANAGER,
@@ -86,150 +91,115 @@ public class RequestHandlerImpl extends AbstractRequestHandlerImpl {
 
             case Unlock:
                 try {
-                    releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
-                    fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
+                    lockManager.releaseLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
+                    logger.info("Lock released for vnfID = " + runtimeContext.getVnfContext().getId());
+                    fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
                 } catch (LockException e) {
-                    //TODO add proper error code and message
-                    //  logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
+                    logger.error("Error during Unlock operation: " + e.getMessage(), e);
                     Params params = new Params().addParam("errorMsg", e.getMessage());
-                    fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
+                    fillStatus(runtimeContext, LCMCommandStatus.LOCKED_VNF_ID, params);
                 }
                 break;
 
             case CheckLock:
                 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
-                fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
+                fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
                 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
                 break;
             default:
-                try {
-                    boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
-                    runtimeContext.setIsLockAcquired(lockAcquired);
-                    callWfOperation(runtimeContext);
-                } catch (LockException e) {
-                    Params params = new Params().addParam("errorMsg", e.getMessage());
-                    fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
-                } finally {
-                    if (runtimeContext.isLockAcquired()) {
-                        final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
-                        if (statusCode % 100 == 2 || statusCode % 100 == 3) {
-                            try {
-                                releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
-                            } catch (LockException e) {
-                                logger.error("Error releasing the lock",e);
-                            }
-                        }
-                    }
-                }
+                callWfOperation(runtimeContext);
         }
     }
 
-    private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
-        lockManager.releaseLock(vnfId, transactionId);
-        logger.info("Lock released for vnfID = " + vnfId);
-    }
 
-    protected void lockWithTimeout(String vnfId, String requestId) throws LockException {
-        long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
-        acquireVNFLock(vnfId, requestId, timeout);
-    }
+    private void callWfOperation(RuntimeContext runtimeContext) {
+        int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
+        if (remainingTTL > 0) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
+            }
 
-    private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
-        if (logger.isTraceEnabled())
-            logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
-        boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
-        if (lockAcquired) {
-            logger.info("Lock acquired for vnfID = " + vnfID);
-        } else {
-            logger.info("vnfID = " + vnfID + " was already locked");
-        }
-        return lockAcquired;
-    }
+            RuntimeContext clonedContext = cloneContext(runtimeContext);
 
-    /**
-     * 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.
-     *
-     * @param vnfId String of VNF ID
-     * @param readOnlyActivity boolean indicator
-     * @param  requestIdentifierString - string contains id uniquely represents the request
-     * @param forceFlag boolean indicator
-     * @throws UnstableVNFException when failed
-     */
-    @Override
-    public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
-        if (logger.isTraceEnabled()) {
-            logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
-        }
+            CommandExecutorInput commandExecutorInput = new CommandExecutorInput();
+            commandExecutorInput.setRuntimeContext(clonedContext);
+            commandExecutorInput.setTtl(remainingTTL);
 
-        if(!readOnlyActivity || !forceFlag || workingStateManager.isVNFStable(vnfId)) {
-            boolean updated = false;
             try {
-                updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
-            }  catch (Exception e) {
-                logger.error("Error updating working state for vnf " + vnfId + e);
-                throw new RuntimeException(e);
-            }
-            if (!updated) {
-                throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
+                commandExecutor.executeCommand(commandExecutorInput);
+                if (logger.isTraceEnabled()) {
+                    logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
+                }
+                fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
+                if (isMetricEnabled) {
+                    ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
+                }
+            } catch (APPCException e) {
+                logger.error("Unexpected Error : " + e.getMessage(), e);
+                String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
+                Params params = new Params().addParam("errorMsg", errorMessage);
+                fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
             }
-        }
-
-        if (logger.isTraceEnabled())
-            logger.trace("Exiting from onRequestExecutionStart ");
-    }
-
-    private boolean isReadOnlyAction(VNFOperation action) {
-        if (VNFOperation.Sync.toString().equals(action) ||
-                VNFOperation.Audit.toString().equals(action) ||
-                VNFOperation.ConfigBackup.toString().equals(action) ||
-                VNFOperation.ConfigBackupDelete.toString().equals(action) ||
-                VNFOperation.ConfigExport.toString().equals(action)){
-            return true;
-        }
-        return false;
-    }
 
-    @Override
-    public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
-        super.onRequestExecutionEnd(runtimeContext,isAAIUpdated);
-        VNFWorkingState workingState;
-        Status status = runtimeContext.getResponseContext().getStatus();
-        if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
-            workingState = VNFWorkingState.STABLE;
         } else {
-            workingState = VNFWorkingState.UNKNOWN;
+            fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
+            storeErrorMessageToLog(runtimeContext,
+                    LoggingConstants.TargetNames.APPC,
+                    LoggingConstants.TargetNames.REQUEST_HANDLER,
+                    EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
+                            runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
+                            runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
+                            String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
         }
+    }
 
-        UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
-                runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
-                runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
 
-        String requestIdentifierString = requestIdentifier.toIdentifierString();
-        workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
-        logger.debug("Reset lock for vnfId " + runtimeContext.getVnfContext().getId());
-        resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
+    private int calculateRemainingTTL(CommonHeader commonHeader) {
+        if (logger.isTraceEnabled()) {
+            logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
+        }
+        long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().getTime());
+        int usedTimeInSeconds = (int) (usedTimeInMillis / 1000);
+        logger.debug("usedTimeInSeconds = " + usedTimeInSeconds + "usedTimeInMillis = " + usedTimeInMillis);
+        // Set ttl value from commonHeader. If not available set it to default
+        Integer inputTTL = (commonHeader.getFlags() == null || commonHeader.getFlags().getTtl() <= 0) ?
+                Integer.parseInt(configuration.getProperty(Constants.DEFAULT_TTL_KEY, String.valueOf(Constants.DEFAULT_TTL))) :
+                commonHeader.getFlags().getTtl();
+        logger.debug("inputTTL = " + inputTTL);
+        Integer remainingTTL = inputTTL - usedTimeInSeconds;
+        logger.debug("Remaining TTL = " + remainingTTL);
+        if (logger.isTraceEnabled())
+            logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
+        return remainingTTL;
     }
 
-    private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
-        if (lockAcquired) {
-            try {
-                releaseVNFLock(vnfId, requestId);
-            } catch (LockException e) {
-                logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
-            }
-        } else if (resetLockTimeout) {
-            try {
-                // reset timeout to previous value
-                lockWithTimeout(vnfId, requestId);
-            } catch (LockException e) {
-                logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
-            }
-        }
+    /*
+    * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
+    * status code and other - depending on DG status). Other properties should not be a problem
+    */
+    private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
+        RuntimeContext other = new RuntimeContext();
+        other.setRequestContext(runtimeContext.getRequestContext());
+        other.setResponseContext(new ResponseContext());
+        other.getResponseContext().setStatus(new Status());
+        other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
+        other.setVnfContext(runtimeContext.getVnfContext());
+        other.setRpcName(runtimeContext.getRpcName());
+        other.setTimeStart(runtimeContext.getTimeStart());
+        other.setTransactionRecord(runtimeContext.getTransactionRecord());
+        return other;
     }
 
+
+    /**
+     * 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.
+     *
+     * @param vnfId                   String of VNF ID
+     * @param readOnlyActivity        boolean indicator
+     * @param forceFlag               boolean indicator
+     */
     @Override
-    public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
-        super.onRequestTTLEnd(runtimeContext,updateAAI);
-        resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
+    public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, boolean forceFlag) {
+
     }
 }