diff options
Diffstat (limited to 'app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/requesthandler/impl/RequestHandlerImpl.java')
-rw-r--r-- | app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/requesthandler/impl/RequestHandlerImpl.java | 839 |
1 files changed, 839 insertions, 0 deletions
diff --git a/app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/requesthandler/impl/RequestHandlerImpl.java b/app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/requesthandler/impl/RequestHandlerImpl.java new file mode 100644 index 000000000..d1303605d --- /dev/null +++ b/app-c/appc/appc-dispatcher/appc-request-handler/appc-request-handler-core/src/main/java/org/openecomp/appc/requesthandler/impl/RequestHandlerImpl.java @@ -0,0 +1,839 @@ +/*- + * ============LICENSE_START======================================================= + * openECOMP : APP-C + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights + * reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.openecomp.appc.requesthandler.impl; + +import org.apache.commons.lang.ObjectUtils; +import org.openecomp.appc.common.constant.Constants; +import org.openecomp.appc.configuration.Configuration; +import org.openecomp.appc.configuration.ConfigurationFactory; +import org.openecomp.appc.domainmodel.lcm.*; +import org.openecomp.appc.exceptions.APPCException; +import org.openecomp.appc.executor.CommandExecutor; +import org.openecomp.appc.executor.UnstableVNFException; +import org.openecomp.appc.executor.objects.CommandExecutorInput; +import org.openecomp.appc.executor.objects.LCMCommandStatus; +import org.openecomp.appc.executor.objects.Params; +import org.openecomp.appc.executor.objects.UniqueRequestIdentifier; +import org.openecomp.appc.i18n.Msg; +import org.openecomp.appc.lifecyclemanager.objects.LifecycleException; +import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException; +import org.openecomp.appc.lockmanager.api.LockException; +import org.openecomp.appc.lockmanager.api.LockManager; +import org.openecomp.appc.logging.LoggingConstants; +import org.openecomp.appc.logging.LoggingUtils; +import org.openecomp.appc.messageadapter.MessageAdapter; +import org.openecomp.appc.messageadapter.impl.MessageAdapterDmaapImpl; +import org.openecomp.appc.metricservice.MetricRegistry; +import org.openecomp.appc.metricservice.MetricService; +import org.openecomp.appc.metricservice.metric.DispatchingFuntionMetric; +import org.openecomp.appc.metricservice.metric.Metric; +import org.openecomp.appc.metricservice.metric.MetricType; +import org.openecomp.appc.metricservice.policy.PublishingPolicy; +import org.openecomp.appc.metricservice.publisher.LogPublisher; +import org.openecomp.appc.requesthandler.RequestHandler; +import org.openecomp.appc.requesthandler.exceptions.*; +import org.openecomp.appc.requesthandler.helper.RequestRegistry; +import org.openecomp.appc.requesthandler.helper.RequestValidator; +import org.openecomp.appc.requesthandler.objects.RequestHandlerInput; +import org.openecomp.appc.requesthandler.objects.RequestHandlerOutput; +import org.openecomp.appc.transactionrecorder.TransactionRecorder; +import org.openecomp.appc.transactionrecorder.objects.TransactionRecord; +import org.openecomp.appc.workingstatemanager.WorkingStateManager; +import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState; +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.att.eelf.i18n.EELFResourceManager; +import org.openecomp.sdnc.sli.SvcLogicContext; +import org.openecomp.sdnc.sli.SvcLogicException; +import org.openecomp.sdnc.sli.SvcLogicResource.QueryStatus; +import org.openecomp.sdnc.sli.aai.AAIService; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.slf4j.MDC; + +import static com.att.eelf.configuration.Configuration.*; + +import java.net.InetAddress; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +/** + * This class provides application logic for the Request/Response Handler Component. + * + */ +public class RequestHandlerImpl implements RequestHandler { + + /** + * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock" + */ + private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout"; + + private CommandExecutor commandExecutor; + + private TransactionRecorder transactionRecorder; + private MessageAdapter messageAdapter; + private RequestValidator requestValidator; + private static MetricRegistry metricRegistry; + private boolean isMetricEnabled = false; + private RequestRegistry requestRegistry; + private LockManager lockManager; + private WorkingStateManager workingStateManager; + private AAIService aaiService; + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class); + + public void setAaiService(AAIService aaiService) { + this.aaiService = aaiService; + } + + public void setTransactionRecorder(TransactionRecorder transactionRecorder) { + this.transactionRecorder = transactionRecorder; + } + + public void setLockManager(LockManager lockManager) { + this.lockManager = lockManager; + } + + public void setRequestValidator(RequestValidator requestValidator) { + this.requestValidator = requestValidator; + } + + public void setMessageAdapter(MessageAdapter messageAdapter) { + this.messageAdapter = messageAdapter; + } + + private static final Configuration configuration = ConfigurationFactory.getConfiguration(); + + public void setWorkingStateManager(WorkingStateManager workingStateManager) { + this.workingStateManager = workingStateManager; + } + + public RequestHandlerImpl() { + requestRegistry = new RequestRegistry(); + messageAdapter = new MessageAdapterDmaapImpl(); + messageAdapter.init(); + Properties properties = configuration.getProperties(); + if (properties != null && properties.getProperty("metric.enabled") != null) { + isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled")); + } + if (isMetricEnabled) { + initMetric(); + } + } + + public void setCommandExecutor(CommandExecutor commandExecutor) { + this.commandExecutor = commandExecutor; + } + + + /** + * It receives requests from the north-bound REST API (Communication) Layer and + * performs following validations. + * 1. VNF exists in A&AI for the given targetID (VnfID) + * 2. For the current VNF Orchestration Status, the command can be executed + * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database + * If any of the validation fails, it returns appropriate response + * + * @param input RequestHandlerInput object which contains request header and other request parameters like command , target Id , payload etc. + * @return response for request as enum with Return code and message. + */ + @Override + public RequestHandlerOutput handleRequest(RequestHandlerInput input) { + if (logger.isTraceEnabled()) + logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")"); + Params params = null; + String vnfId = null, vnfType = null, errorMessage = null; + Date startTime = new Date(System.currentTimeMillis()); + RequestHandlerOutput output = null; + setInitialLogProperties(input.getRequestContext()); + + RuntimeContext runtimeContext = new RuntimeContext(); + runtimeContext.setRequestContext(input.getRequestContext()); + runtimeContext.setTimeStart(startTime); + runtimeContext.setRpcName(input.getRpcName()); + + final ResponseContext responseContext = new ResponseContext(); + responseContext.setStatus(new Status()); + responseContext.setAdditionalContext(new HashMap<String, String>(4)); + responseContext.setCommonHeader(input.getRequestContext().getCommonHeader()); + runtimeContext.setResponseContext(responseContext); + runtimeContext.getResponseContext().setStatus(new Status()); + + vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(); + + try { + + requestValidator.validateRequest(runtimeContext); + + handleRequest(runtimeContext); + + final int statusCode = runtimeContext.getResponseContext().getStatus().getCode(); + if (statusCode % 100 == 2 || statusCode % 100 == 3) { + createTransactionRecord(runtimeContext); + } + output = new RequestHandlerOutput(); + output.setResponseContext(runtimeContext.getResponseContext()); + + } catch (VNFNotFoundException e) { + errorMessage = e.getMessage(); + String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId); + storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage); + params = new Params().addParam("vnfId", vnfId); + output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params); + } catch (NoTransitionDefinedException e) { + errorMessage = e.getMessage(); + String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name()); + params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState); + output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params); + storeErrorMessageToLog(runtimeContext, + LoggingConstants.TargetNames.APPC, + LoggingConstants.TargetNames.STATE_MACHINE, + logMessage); + } catch (LifecycleException e) { + errorMessage = e.getMessage(); + params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState); + output = buildRequestHandlerOutput(LCMCommandStatus.ACTION_NOT_SUPPORTED, params); + } catch (UnstableVNFException e) { + errorMessage = e.getMessage(); + params = new Params().addParam("vnfId", vnfId); + output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params); + } catch (WorkflowNotFoundException e) { + errorMessage = e.getMessage(); + String vnfTypeVersion = e.vnfTypeVersion; + params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion); + output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params); + } catch (DGWorkflowNotFoundException e) { + errorMessage = e.getMessage(); + String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name()); + storeErrorMessageToLog(runtimeContext, + LoggingConstants.TargetNames.APPC, + LoggingConstants.TargetNames.WORKFLOW_MANAGER, + logMessage); + params = new Params().addParam("actionName", input.getRequestContext().getAction().name()) + .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion); + output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params); + } catch (RequestExpiredException e) { + errorMessage = e.getMessage(); + params = new Params().addParam("actionName", input.getRequestContext().getAction().name()); + output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params); + } catch (InvalidInputException e) { + errorMessage = e.getMessage() != null ? e.getMessage() : e.toString(); + params = new Params().addParam("errorMsg", errorMessage); + output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params); + } catch (DuplicateRequestException e) { + errorMessage = e.getMessage(); + output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null); + } catch (Exception e) { + storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage()); + errorMessage = e.getMessage() != null ? e.getMessage() : e.toString(); + params = new Params().addParam("errorMsg", errorMessage); + output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params); + } finally { + try { + if (logger.isDebugEnabled() && errorMessage != null) + logger.debug("error occurred in handleRequest " + errorMessage); + logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())); + logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode())); + + runtimeContext.setResponseContext(output.getResponseContext()); + if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) { + if (isMetricEnabled) { + ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest(); + } + removeRequestFromRegistry(input.getRequestContext().getCommonHeader()); + } + } finally { + storeAuditLogRecord(runtimeContext); + storeMetricLogRecord(runtimeContext); + clearRequestLogProperties(); + } + } + if (logger.isTraceEnabled()) { + logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")"); + } + return output; + } + + private void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) { + LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ? + String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "", + runtimeContext.getResponseContext().getStatus() != null ? + String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "", + targetEntity, + targetServiceName, + additionalMessage, + this.getClass().getCanonicalName()); + } + + private void createTransactionRecord(RuntimeContext runtimeContext) { + TransactionRecord transactionRecord = new TransactionRecord(); + transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp()); + transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId()); + transactionRecord.setStartTime(runtimeContext.getTimeStart()); + transactionRecord.setEndTime(new Date(System.currentTimeMillis())); + transactionRecord.setTargetID(runtimeContext.getVnfContext().getId()); + transactionRecord.setTargetType(runtimeContext.getVnfContext().getType()); + transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name()); + transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode())); + transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage()); + transactionRecorder.store(transactionRecord); + } + + private void handleRequest(RuntimeContext runtimeContext) { + + switch (runtimeContext.getRequestContext().getAction()) { + case Lock: + try { + lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId()); + fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null); + } catch (LockException e) { + Params params = new Params().addParam("errorMsg", e.getMessage()); + fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params); + storeErrorMessageToLog(runtimeContext, + LoggingConstants.TargetNames.APPC, + LoggingConstants.TargetNames.LOCK_MANAGER, + EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId())); + } + + break; + + case Unlock: + try { + releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId()); + 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())); + Params params = new Params().addParam("errorMsg", e.getMessage()); + fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params); + } + break; + + case CheckLock: + boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId()); + 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()); + //TODO add logger call + } catch (LockException e) { + //ignore + } + } + } + } + } + + } + + 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); + } + + RuntimeContext clonedContext = cloneContext(runtimeContext); + + CommandExecutorInput commandExecutorInput = new CommandExecutorInput(); + commandExecutorInput.setRuntimeContext(clonedContext); + commandExecutorInput.setTtl(remainingTTL); + + try { + 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) { + String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString(); + Params params = new Params().addParam("errorMsg", errorMessage); + fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params); + } + + } else { + 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()))); + } + } + + private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) { + runtimeContext.getResponseContext().getStatus().setCode(lcmCommandStatus.getResponseCode()); + runtimeContext.getResponseContext().getStatus().setMessage(lcmCommandStatus.getFormattedMessage(params)); + } + + /* + * 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.setIsLockAcquired(runtimeContext.isLockAcquired()); + return other; + } + + + private void clearRequestLogProperties() { + try { + MDC.remove(MDC_KEY_REQUEST_ID); + MDC.remove(MDC_SERVICE_INSTANCE_ID); + MDC.remove(MDC_SERVICE_NAME); + MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME); + MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY); + } catch (Exception e) { + + } + } + + private void removeRequestFromRegistry(CommonHeader commonHeader) { + if (logger.isTraceEnabled()) + logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader)); + requestRegistry.removeRequest( + new UniqueRequestIdentifier(commonHeader.getOriginatorId(), + commonHeader.getRequestId(), + commonHeader.getSubRequestId())); + } + + 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; + } + + private 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 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); + } + } + } + + private void releaseVNFLock(String vnfId, String transactionId) throws LockException { + lockManager.releaseLock(vnfId, transactionId); + logger.info("Lock released for vnfID = " + vnfId); + } + + private void setInitialLogProperties(RequestContext requestContext) { + + try { + MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId()); + if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) { + MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId()); + } + MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId()); + MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong! + MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); + MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName()); + MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name()); + MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId()); + + } catch (Exception e) { + logger.debug(e.getMessage()); + } + } catch (RuntimeException e) { + //ignore + } + } + + + 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()); + logger.debug("usedTimeInMillis = " + usedTimeInMillis); + int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000); + logger.debug("usedTimeInSeconds = " + usedTimeInSeconds); + Integer inputTTL = this.getInputTTL(commonHeader); + 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 Integer getInputTTL(CommonHeader header) { + if (logger.isTraceEnabled()) + logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header)); + if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) { + String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL)); + Integer defaultTTL = Integer.parseInt(defaultTTLStr); + if (logger.isTraceEnabled()) + logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")"); + return defaultTTL; + } + if (logger.isTraceEnabled()) + logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")"); + + return header.getFlags().getTtl(); + } + + private boolean isValidTTL(String ttl) { + if (ttl == null || ttl.length() == 0) { + if (logger.isTraceEnabled()) + logger.trace("Exiting from getInputTTL with (result = false)"); + return false; + } + try { + Integer i = Integer.parseInt(ttl); + return (i > 0); + } catch (NumberFormatException e) { + if (logger.isTraceEnabled()) + logger.trace("Exiting from getInputTTL with (result = false)"); + return false; + } + } + + private Boolean isLoggingEnabled() { + String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG)); + Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr); + return defaultFlag; + } + + private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) { + RequestHandlerOutput output = new RequestHandlerOutput(); + ResponseContext responseContext = new ResponseContext(); + org.openecomp.appc.domainmodel.lcm.Status status = new org.openecomp.appc.domainmodel.lcm.Status(); + status.setCode(response.getResponseCode()); + status.setMessage(response.getFormattedMessage(params)); + responseContext.setStatus(status); + output.setResponseContext(responseContext); + return output; + } + + /** + * 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. + * + * @return true in case AAI updates are successful. false for any error or exception. + */ + @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); + } + try { + boolean updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag); + if (!updated) { + throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId); + } + } catch (Exception e) { + logger.error("Error updating working state for vnf " + vnfId + e); + throw new RuntimeException(e); + } + + if (logger.isTraceEnabled()) + logger.trace("Exiting from onRequestExecutionStart "); + } + + /** + * This method perform following operations required after execution of workflow. + * It posts asynchronous response to message bus (DMaaP). + * Unlock VNF Id + * Removes request from request registry. + * Generate audit logs. + * Adds transaction record to database id if transaction logging is enabled. + * + * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion. + */ + @Override + public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) { + if (logger.isTraceEnabled()) { + logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext)); + } + + postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext()); + requestRegistry.removeRequest( + new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(), + runtimeContext.getResponseContext().getCommonHeader().getRequestId(), + runtimeContext.getResponseContext().getCommonHeader().getSubRequestId())); + resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true); + Status status = runtimeContext.getResponseContext().getStatus(); + + VNFWorkingState workingState; + if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) { + workingState = VNFWorkingState.STABLE; + } else { + workingState = VNFWorkingState.UNKNOWN; + } + + 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); + + + storeAuditLogRecord(runtimeContext); + + if (isLoggingEnabled()) { + createTransactionRecord(runtimeContext); + } + } + + private void storeAuditLogRecord(RuntimeContext runtimeContext) { + LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(), + new Date(System.currentTimeMillis()), + String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()), + runtimeContext.getResponseContext().getStatus().getMessage(), + this.getClass().getCanonicalName()); + } + + private void storeMetricLogRecord(RuntimeContext runtimeContext) { + LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(), + new Date(System.currentTimeMillis()), + LoggingConstants.TargetNames.APPC, + runtimeContext.getRequestContext().getAction().name(), + runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR, + String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()), + runtimeContext.getResponseContext().getStatus().getMessage(), + this.getClass().getCanonicalName()); + } + + private boolean isReadOnlyAction(VNFOperation action) { + return VNFOperation.Sync == action + || VNFOperation.Audit == action; + } + + + //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse + private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) { + if (logger.isTraceEnabled()) { + logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext)); + } + /*boolean updated = updateAsyncResponseStatus(responseContext, isTTLEnd, aaiUpdateSuccess); + */ + boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext); + if (!callbackResponse) { + logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext); + } + if (logger.isTraceEnabled()) + logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")"); + } + + //returns true if asyncResponse was modified + /* private boolean updateAsyncResponseStatus(ResponseContext asyncResponse, boolean isTTLEnd, boolean aaiUpdateSuccess) { + boolean updated = false; + if (logger.isTraceEnabled()) + logger.trace("Entering to updateAsyncResponseStatus with AsyncResponse = "+ObjectUtils.toString(asyncResponse)+ ", isTTLEnd = "+ ObjectUtils.toString(isTTLEnd)+ ", aaiUpdateSuccess = "+ ObjectUtils.toString(aaiUpdateSuccess)); + if(!aaiUpdateSuccess){ + if (asyncResponse.getStatus().getCode() == 0 || asyncResponse.getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()) { + asyncResponse.getStatus().setCode(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseCode()); + asyncResponse.getStatus().setMessage(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseMessage()); + updated = true; + } + }else if(isTTLEnd){ + asyncResponse.getStatus().setCode(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseCode()); + asyncResponse.getStatus().setMessage(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage()); + updated = true; + } + if (logger.isTraceEnabled()) + logger.trace("Exiting from updateAsyncResponseStatus with (asyncResponse = "+ ObjectUtils.toString(asyncResponse)+")"); + return updated; + }*/ + + + /** + * This method perform following operations required if TTL ends when request still waiting in execution queue . + * It posts asynchronous response to message bus (DMaaP). + * Unlock VNF Id + * Removes request from request registry. + * + * @param runtimeContext AsyncResponse object which contains VNF Id , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId; + * @param updateAAI boolean flag which indicate AAI upodate status after request completion. + */ + @Override + public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) { + if (logger.isTraceEnabled()) { + logger.trace("Entering to onRequestTTLEnd with " + + "AsyncResponse = " + ObjectUtils.toString(runtimeContext) + + ", updateAAI = " + ObjectUtils.toString(updateAAI)); + } + logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage()); + fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null); + postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext()); + resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true); + requestRegistry.removeRequest( + new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(), + runtimeContext.getResponseContext().getCommonHeader().getRequestId(), + runtimeContext.getResponseContext().getCommonHeader().getSubRequestId())); + } + + private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException { + String key = "vnf-id = '" + vnf_id + "'"; + if (logger.isTraceEnabled()) { + logger.trace("Entering to getVnfdata with " + + "vnfId = " + vnf_id + + ", prefix = " + prefix + + ", SvcLogicContex = " + ObjectUtils.toString(ctx)); + } + try { + QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx); + if (QueryStatus.NOT_FOUND.equals(response)) { + throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id); + } else if (QueryStatus.FAILURE.equals(response)) { + throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id); + } + logger.info("AAIResponse: " + response.toString()); + } catch (SvcLogicException e) { + logger.error("Error in getVnfdata " + e); + throw new RuntimeException(e); + } + if (logger.isTraceEnabled()) { + logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")"); + } + return ctx; + } + + private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException { + if (logger.isTraceEnabled()) { + logger.trace("Entering to postVnfdata with " + + "vnfId = " + vnf_id + + ", status = " + status + + ", prefix = " + prefix + + ", SvcLogicContext = " + ObjectUtils.toString(ctx)); + } + String key = "vnf-id = '" + vnf_id + "'"; + Map<String, String> data = new HashMap<>(); + data.put("orchestration-status", status); + try { + QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx); + if (QueryStatus.NOT_FOUND.equals(response)) { + throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id); + } + logger.info("AAIResponse: " + response.toString()); + if (response.toString().equals("SUCCESS")) { + if (logger.isTraceEnabled()) { + logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")"); + } + return true; + } + + } catch (SvcLogicException e) { + logger.error("Error in postVnfdata " + e); + throw new RuntimeException(e); + } + if (logger.isTraceEnabled()) { + logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")"); + } + return false; + } + + private void initMetric() { + if (logger.isDebugEnabled()) + logger.debug("Metric getting initialized"); + MetricService metricService = getMetricservice(); + metricRegistry = metricService.createRegistry("APPC"); + DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory(). + dispatchingFunctionCounterBuilder(). + withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER). + withAcceptRequestValue(0) + .withRejectRequestValue(0) + .build(); + if (metricRegistry.register(dispatchingFuntionMetric)) { + Metric[] metrics = new Metric[]{dispatchingFuntionMetric}; + LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics); + LogPublisher[] logPublishers = new LogPublisher[1]; + logPublishers[0] = logPublisher; + PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory(). + scheduledPolicyBuilder().withPublishers(logPublishers). + withMetrics(metrics). + build(); + if (logger.isDebugEnabled()) + logger.debug("Policy getting initialized"); + manuallyScheduledPublishingPolicy.init(); + if (logger.isDebugEnabled()) + logger.debug("Metric initialized"); + } + } + + + private MetricService getMetricservice() { + BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext(); + ServiceReference sref = bctx.getServiceReference(MetricService.class.getName()); + if (sref != null) { + logger.info("Metric Service from bundlecontext"); + return (MetricService) bctx.getService(sref); + } else { + logger.info("Metric Service error from bundlecontext"); + logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService"); + return null; + } + } +} |