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.LCMCommandStatus;
33 import org.openecomp.appc.executor.objects.Params;
34 import org.openecomp.appc.executor.objects.UniqueRequestIdentifier;
35 import org.openecomp.appc.i18n.Msg;
36 import org.openecomp.appc.lifecyclemanager.objects.LifecycleException;
37 import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException;
38 import org.openecomp.appc.lockmanager.api.LockException;
39 import org.openecomp.appc.lockmanager.api.LockManager;
40 import org.openecomp.appc.logging.LoggingConstants;
41 import org.openecomp.appc.logging.LoggingUtils;
42 import org.openecomp.appc.messageadapter.MessageAdapter;
43 import org.openecomp.appc.messageadapter.impl.MessageAdapterDmaapImpl;
44 import org.openecomp.appc.metricservice.MetricRegistry;
45 import org.openecomp.appc.metricservice.MetricService;
46 import org.openecomp.appc.metricservice.metric.DispatchingFuntionMetric;
47 import org.openecomp.appc.metricservice.metric.Metric;
48 import org.openecomp.appc.metricservice.metric.MetricType;
49 import org.openecomp.appc.metricservice.policy.PublishingPolicy;
50 import org.openecomp.appc.metricservice.publisher.LogPublisher;
51 import org.openecomp.appc.requesthandler.RequestHandler;
52 import org.openecomp.appc.requesthandler.exceptions.*;
53 import org.openecomp.appc.requesthandler.helper.RequestRegistry;
54 import org.openecomp.appc.requesthandler.helper.RequestValidator;
55 import org.openecomp.appc.requesthandler.objects.RequestHandlerInput;
56 import org.openecomp.appc.requesthandler.objects.RequestHandlerOutput;
57 import org.openecomp.appc.transactionrecorder.TransactionRecorder;
58 import org.openecomp.appc.transactionrecorder.objects.TransactionRecord;
59 import org.openecomp.appc.workingstatemanager.WorkingStateManager;
60 import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
61 import com.att.eelf.configuration.EELFLogger;
62 import com.att.eelf.configuration.EELFManager;
63 import com.att.eelf.i18n.EELFResourceManager;
64 import org.openecomp.sdnc.sli.SvcLogicContext;
65 import org.openecomp.sdnc.sli.SvcLogicException;
66 import org.openecomp.sdnc.sli.SvcLogicResource.QueryStatus;
67 import org.openecomp.sdnc.sli.aai.AAIService;
68 import org.osgi.framework.BundleContext;
69 import org.osgi.framework.FrameworkUtil;
70 import org.osgi.framework.ServiceReference;
73 import static com.att.eelf.configuration.Configuration.*;
75 import java.net.InetAddress;
76 import java.time.Instant;
77 import java.time.temporal.ChronoUnit;
78 import java.util.Date;
79 import java.util.HashMap;
81 import java.util.Properties;
84 * This class provides application logic for the Request/Response Handler Component.
87 public class RequestHandlerImpl implements RequestHandler {
90 * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
92 private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout";
94 private CommandExecutor commandExecutor;
96 private TransactionRecorder transactionRecorder;
97 private MessageAdapter messageAdapter;
98 private RequestValidator requestValidator;
99 private static MetricRegistry metricRegistry;
100 private boolean isMetricEnabled = false;
101 private RequestRegistry requestRegistry;
102 private LockManager lockManager;
103 private WorkingStateManager workingStateManager;
104 private AAIService aaiService;
106 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
108 public void setAaiService(AAIService aaiService) {
109 this.aaiService = aaiService;
112 public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
113 this.transactionRecorder = transactionRecorder;
116 public void setLockManager(LockManager lockManager) {
117 this.lockManager = lockManager;
120 public void setRequestValidator(RequestValidator requestValidator) {
121 this.requestValidator = requestValidator;
124 public void setMessageAdapter(MessageAdapter messageAdapter) {
125 this.messageAdapter = messageAdapter;
128 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
130 public void setWorkingStateManager(WorkingStateManager workingStateManager) {
131 this.workingStateManager = workingStateManager;
134 public RequestHandlerImpl() {
135 requestRegistry = new RequestRegistry();
136 messageAdapter = new MessageAdapterDmaapImpl();
137 messageAdapter.init();
138 Properties properties = configuration.getProperties();
139 if (properties != null && properties.getProperty("metric.enabled") != null) {
140 isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
142 if (isMetricEnabled) {
147 public void setCommandExecutor(CommandExecutor commandExecutor) {
148 this.commandExecutor = commandExecutor;
153 * It receives requests from the north-bound REST API (Communication) Layer and
154 * performs following validations.
155 * 1. VNF exists in A&AI for the given targetID (VnfID)
156 * 2. For the current VNF Orchestration Status, the command can be executed
157 * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
158 * If any of the validation fails, it returns appropriate response
160 * @param input RequestHandlerInput object which contains request header and other request parameters like command , target Id , payload etc.
161 * @return response for request as enum with Return code and message.
164 public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
165 if (logger.isTraceEnabled())
166 logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
167 Params params = null;
168 String vnfId = null, vnfType = null, errorMessage = null;
169 Instant startTime = Instant.now();
170 RequestHandlerOutput output = null;
171 setInitialLogProperties(input.getRequestContext());
173 RuntimeContext runtimeContext = new RuntimeContext();
174 runtimeContext.setRequestContext(input.getRequestContext());
175 runtimeContext.setTimeStart(startTime);
176 runtimeContext.setRpcName(input.getRpcName());
178 final ResponseContext responseContext = new ResponseContext();
179 responseContext.setStatus(new Status(0, null));
180 responseContext.setAdditionalContext(new HashMap<String, String>(4));
181 responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
182 runtimeContext.setResponseContext(responseContext);
183 runtimeContext.getResponseContext().setStatus(new Status(0, null));
185 vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
189 requestValidator.validateRequest(runtimeContext);
191 handleRequest(runtimeContext);
193 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
194 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
195 createTransactionRecord(runtimeContext);
197 output = new RequestHandlerOutput();
198 output.setResponseContext(runtimeContext.getResponseContext());
200 } catch (VNFNotFoundException e) {
201 errorMessage = e.getMessage();
202 String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
203 storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
204 params = new Params().addParam("vnfId", vnfId);
205 output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
206 } catch (NoTransitionDefinedException e) {
207 errorMessage = e.getMessage();
208 String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
209 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
210 output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
211 storeErrorMessageToLog(runtimeContext,
212 LoggingConstants.TargetNames.APPC,
213 LoggingConstants.TargetNames.STATE_MACHINE,
215 } catch (LifecycleException e) {
216 errorMessage = e.getMessage();
217 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
218 output = buildRequestHandlerOutput(LCMCommandStatus.ACTION_NOT_SUPPORTED, params);
219 } catch (UnstableVNFException e) {
220 errorMessage = e.getMessage();
221 params = new Params().addParam("vnfId", vnfId);
222 output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
223 } catch (WorkflowNotFoundException e) {
224 errorMessage = e.getMessage();
225 String vnfTypeVersion = e.vnfTypeVersion;
226 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
227 output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
228 } catch (DGWorkflowNotFoundException e) {
229 errorMessage = e.getMessage();
230 String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
231 storeErrorMessageToLog(runtimeContext,
232 LoggingConstants.TargetNames.APPC,
233 LoggingConstants.TargetNames.WORKFLOW_MANAGER,
235 params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
236 .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
237 output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
238 } catch (RequestExpiredException e) {
239 errorMessage = e.getMessage();
240 params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
241 output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
242 } catch (InvalidInputException e) {
243 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
244 params = new Params().addParam("errorMsg", errorMessage);
245 output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
246 } catch (DuplicateRequestException e) {
247 errorMessage = e.getMessage();
248 output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
249 } catch (Exception e) {
250 storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
251 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
252 params = new Params().addParam("errorMsg", errorMessage);
253 output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
256 if (logger.isDebugEnabled() && errorMessage != null)
257 logger.debug("error occurred in handleRequest " + errorMessage);
258 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
259 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
261 runtimeContext.setResponseContext(output.getResponseContext());
262 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
263 if (isMetricEnabled) {
264 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
266 removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
269 storeAuditLogRecord(runtimeContext);
270 storeMetricLogRecord(runtimeContext);
271 clearRequestLogProperties();
274 if (logger.isTraceEnabled()) {
275 logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
280 private void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
281 LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
282 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
283 runtimeContext.getResponseContext().getStatus() != null ?
284 String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
288 this.getClass().getCanonicalName());
291 private void createTransactionRecord(RuntimeContext runtimeContext) {
292 TransactionRecord transactionRecord = new TransactionRecord();
293 transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
294 transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
295 transactionRecord.setStartTime(runtimeContext.getTimeStart());
296 transactionRecord.setEndTime(Instant.now());
297 transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
298 transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
299 transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
300 transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
301 transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
302 transactionRecorder.store(transactionRecord);
305 private void handleRequest(RuntimeContext runtimeContext) {
307 switch (runtimeContext.getRequestContext().getAction()) {
310 lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
311 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
312 } catch (LockException e) {
313 Params params = new Params().addParam("errorMsg", e.getMessage());
314 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
315 storeErrorMessageToLog(runtimeContext,
316 LoggingConstants.TargetNames.APPC,
317 LoggingConstants.TargetNames.LOCK_MANAGER,
318 EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
325 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
326 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
327 } catch (LockException e) {
328 //TODO add proper error code and message
329 // logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
330 Params params = new Params().addParam("errorMsg", e.getMessage());
331 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
336 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
337 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
338 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
342 boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
343 runtimeContext.setIsLockAcquired(lockAcquired);
344 callWfOperation(runtimeContext);
345 } catch (LockException e) {
346 Params params = new Params().addParam("errorMsg", e.getMessage());
347 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
349 if (runtimeContext.isLockAcquired()) {
350 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
351 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
353 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
354 //TODO add logger call
355 } catch (LockException e) {
365 private void callWfOperation(RuntimeContext runtimeContext) {
366 int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
367 if (remainingTTL > 0) {
368 if (logger.isDebugEnabled()) {
369 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
372 RuntimeContext commandExecutorInput = cloneContext(runtimeContext);
375 commandExecutor.executeCommand(commandExecutorInput);
376 if(logger.isTraceEnabled()) {
377 logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
379 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
380 if (isMetricEnabled) {
381 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
383 } catch (APPCException e) {
384 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
385 Params params = new Params().addParam("errorMsg", errorMessage);
386 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
390 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
391 storeErrorMessageToLog(runtimeContext,
392 LoggingConstants.TargetNames.APPC,
393 LoggingConstants.TargetNames.REQUEST_HANDLER,
394 EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
395 runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
396 runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
397 String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
401 private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
402 runtimeContext.getResponseContext().setStatus(lcmCommandStatus.toStatus(params));
406 * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
407 * status code and other - depending on DG status). Other properties should not be a problem
409 private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
410 RuntimeContext other = new RuntimeContext();
411 other.setRequestContext(runtimeContext.getRequestContext());
412 other.setResponseContext(new ResponseContext());
413 other.getResponseContext().setStatus(new Status(0, null));
414 other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
415 other.setVnfContext(runtimeContext.getVnfContext());
416 other.setRpcName(runtimeContext.getRpcName());
417 other.setTimeStart(runtimeContext.getTimeStart());
418 other.setIsLockAcquired(runtimeContext.isLockAcquired());
423 private void clearRequestLogProperties() {
425 MDC.remove(MDC_KEY_REQUEST_ID);
426 MDC.remove(MDC_SERVICE_INSTANCE_ID);
427 MDC.remove(MDC_SERVICE_NAME);
428 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
429 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
430 } catch (Exception e) {
435 private void removeRequestFromRegistry(CommonHeader commonHeader) {
436 if (logger.isTraceEnabled())
437 logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
438 requestRegistry.removeRequest(
439 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
440 commonHeader.getRequestId(),
441 commonHeader.getSubRequestId()));
444 private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
445 if (logger.isTraceEnabled())
446 logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
447 boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
449 logger.info("Lock acquired for vnfID = " + vnfID);
451 logger.info("vnfID = " + vnfID + " was already locked");
456 private void lockWithTimeout(String vnfId, String requestId) throws LockException {
457 long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
458 acquireVNFLock(vnfId, requestId, timeout);
461 private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
464 releaseVNFLock(vnfId, requestId);
465 } catch (LockException e) {
466 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
470 } else if (resetLockTimeout) {
472 // reset timeout to previous value
473 lockWithTimeout(vnfId, requestId);
474 } catch (LockException e) {
475 logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
480 private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
481 lockManager.releaseLock(vnfId, transactionId);
482 logger.info("Lock released for vnfID = " + vnfId);
485 private void setInitialLogProperties(RequestContext requestContext) {
488 MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
489 if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
490 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
492 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
493 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
495 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
496 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
497 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
498 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
499 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
501 } catch (Exception e) {
502 logger.debug(e.getMessage());
504 } catch (RuntimeException e) {
510 private int calculateRemainingTTL(CommonHeader commonHeader) {
511 if (logger.isTraceEnabled()) {
512 logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
514 long usedTimeInMillis = ChronoUnit.MILLIS.between(commonHeader.getTimeStamp(), Instant.now());
515 logger.debug("usedTimeInMillis = " + usedTimeInMillis);
516 int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
517 logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
518 Integer inputTTL = this.getInputTTL(commonHeader);
519 logger.debug("inputTTL = " + inputTTL);
520 Integer remainingTTL = inputTTL - usedTimeInSeconds;
521 logger.debug("Remaining TTL = " + remainingTTL);
522 if (logger.isTraceEnabled())
523 logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
527 private Integer getInputTTL(CommonHeader header) {
528 if (logger.isTraceEnabled())
529 logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
530 if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
531 String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
532 Integer defaultTTL = Integer.parseInt(defaultTTLStr);
533 if (logger.isTraceEnabled())
534 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
537 if (logger.isTraceEnabled())
538 logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
540 return header.getFlags().getTtl();
543 private boolean isValidTTL(String ttl) {
544 if (ttl == null || ttl.length() == 0) {
545 if (logger.isTraceEnabled())
546 logger.trace("Exiting from getInputTTL with (result = false)");
550 Integer i = Integer.parseInt(ttl);
552 } catch (NumberFormatException e) {
553 if (logger.isTraceEnabled())
554 logger.trace("Exiting from getInputTTL with (result = false)");
559 private Boolean isLoggingEnabled() {
560 String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
561 Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr);
565 private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
566 RequestHandlerOutput output = new RequestHandlerOutput();
567 ResponseContext responseContext = new ResponseContext();
568 responseContext.setStatus(response.toStatus(params));
569 output.setResponseContext(responseContext);
574 * 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.
576 * @return true in case AAI updates are successful. false for any error or exception.
579 public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
580 if (logger.isTraceEnabled()) {
581 logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
584 boolean updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
586 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
588 } catch (Exception e) {
589 logger.error("Error updating working state for vnf " + vnfId + e);
590 throw new RuntimeException(e);
593 if (logger.isTraceEnabled())
594 logger.trace("Exiting from onRequestExecutionStart ");
598 * This method perform following operations required after execution of workflow.
599 * It posts asynchronous response to message bus (DMaaP).
601 * Removes request from request registry.
602 * Generate audit logs.
603 * Adds transaction record to database id if transaction logging is enabled.
605 * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
608 public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
609 if (logger.isTraceEnabled()) {
610 logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
613 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
614 requestRegistry.removeRequest(
615 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
616 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
617 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
618 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
619 Status status = runtimeContext.getResponseContext().getStatus();
621 VNFWorkingState workingState;
622 if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
623 workingState = VNFWorkingState.STABLE;
625 workingState = VNFWorkingState.UNKNOWN;
628 UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
629 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
630 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
632 String requestIdentifierString = requestIdentifier.toIdentifierString();
633 workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
636 storeAuditLogRecord(runtimeContext);
638 if (isLoggingEnabled()) {
639 createTransactionRecord(runtimeContext);
643 private void storeAuditLogRecord(RuntimeContext runtimeContext) {
644 LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
646 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
647 runtimeContext.getResponseContext().getStatus().getMessage(),
648 this.getClass().getCanonicalName());
651 private void storeMetricLogRecord(RuntimeContext runtimeContext) {
652 LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
654 LoggingConstants.TargetNames.APPC,
655 runtimeContext.getRequestContext().getAction().name(),
656 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
657 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
658 runtimeContext.getResponseContext().getStatus().getMessage(),
659 this.getClass().getCanonicalName());
662 private boolean isReadOnlyAction(VNFOperation action) {
663 return VNFOperation.Sync == action
664 || VNFOperation.Audit == action;
668 //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse
669 private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) {
670 if (logger.isTraceEnabled()) {
671 logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
673 boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
674 if (!callbackResponse) {
675 logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
677 if (logger.isTraceEnabled())
678 logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
682 * This method perform following operations required if TTL ends when request still waiting in execution queue .
683 * It posts asynchronous response to message bus (DMaaP).
685 * Removes request from request registry.
687 * @param runtimeContext AsyncResponse object which contains VNF Id , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
688 * @param updateAAI boolean flag which indicate AAI upodate status after request completion.
691 public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
692 if (logger.isTraceEnabled()) {
693 logger.trace("Entering to onRequestTTLEnd with " +
694 "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
695 ", updateAAI = " + ObjectUtils.toString(updateAAI));
697 logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
698 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
699 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
700 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
701 requestRegistry.removeRequest(
702 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
703 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
704 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
707 private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
708 String key = "vnf-id = '" + vnf_id + "'";
709 if (logger.isTraceEnabled()) {
710 logger.trace("Entering to getVnfdata with " +
711 "vnfId = " + vnf_id +
712 ", prefix = " + prefix +
713 ", SvcLogicContex = " + ObjectUtils.toString(ctx));
716 QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx);
717 if (QueryStatus.NOT_FOUND.equals(response)) {
718 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
719 } else if (QueryStatus.FAILURE.equals(response)) {
720 throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id);
722 logger.info("AAIResponse: " + response.toString());
723 } catch (SvcLogicException e) {
724 logger.error("Error in getVnfdata " + e);
725 throw new RuntimeException(e);
727 if (logger.isTraceEnabled()) {
728 logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
733 private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
734 if (logger.isTraceEnabled()) {
735 logger.trace("Entering to postVnfdata with " +
736 "vnfId = " + vnf_id +
737 ", status = " + status +
738 ", prefix = " + prefix +
739 ", SvcLogicContext = " + ObjectUtils.toString(ctx));
741 String key = "vnf-id = '" + vnf_id + "'";
742 Map<String, String> data = new HashMap<>();
743 data.put("orchestration-status", status);
745 QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx);
746 if (QueryStatus.NOT_FOUND.equals(response)) {
747 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
749 logger.info("AAIResponse: " + response.toString());
750 if (response.toString().equals("SUCCESS")) {
751 if (logger.isTraceEnabled()) {
752 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")");
757 } catch (SvcLogicException e) {
758 logger.error("Error in postVnfdata " + e);
759 throw new RuntimeException(e);
761 if (logger.isTraceEnabled()) {
762 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
767 private void initMetric() {
768 if (logger.isDebugEnabled())
769 logger.debug("Metric getting initialized");
770 MetricService metricService = getMetricservice();
771 metricRegistry = metricService.createRegistry("APPC");
772 DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
773 dispatchingFunctionCounterBuilder().
774 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
775 withAcceptRequestValue(0)
776 .withRejectRequestValue(0)
778 if (metricRegistry.register(dispatchingFuntionMetric)) {
779 Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
780 LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
781 LogPublisher[] logPublishers = new LogPublisher[1];
782 logPublishers[0] = logPublisher;
783 PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
784 scheduledPolicyBuilder().withPublishers(logPublishers).
785 withMetrics(metrics).
787 if (logger.isDebugEnabled())
788 logger.debug("Policy getting initialized");
789 manuallyScheduledPublishingPolicy.init();
790 if (logger.isDebugEnabled())
791 logger.debug("Metric initialized");
796 private MetricService getMetricservice() {
797 BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
798 ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
800 logger.info("Metric Service from bundlecontext");
801 return (MetricService) bctx.getService(sref);
803 logger.info("Metric Service error from bundlecontext");
804 logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");