2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.openecomp.appc.requesthandler.impl;
24 import org.apache.commons.lang.ObjectUtils;
25 import org.openecomp.appc.common.constant.Constants;
26 import org.openecomp.appc.configuration.Configuration;
27 import org.openecomp.appc.configuration.ConfigurationFactory;
28 import org.openecomp.appc.domainmodel.lcm.*;
29 import org.openecomp.appc.exceptions.APPCException;
30 import org.openecomp.appc.executor.CommandExecutor;
31 import org.openecomp.appc.executor.UnstableVNFException;
32 import org.openecomp.appc.executor.objects.CommandExecutorInput;
33 import org.openecomp.appc.executor.objects.LCMCommandStatus;
34 import org.openecomp.appc.executor.objects.Params;
35 import org.openecomp.appc.executor.objects.UniqueRequestIdentifier;
36 import org.openecomp.appc.i18n.Msg;
37 import org.openecomp.appc.lifecyclemanager.objects.LifecycleException;
38 import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException;
39 import org.openecomp.appc.lockmanager.api.LockException;
40 import org.openecomp.appc.lockmanager.api.LockManager;
41 import org.openecomp.appc.logging.LoggingConstants;
42 import org.openecomp.appc.logging.LoggingUtils;
43 import org.openecomp.appc.messageadapter.MessageAdapter;
44 import org.openecomp.appc.messageadapter.impl.MessageAdapterDmaapImpl;
45 import org.openecomp.appc.metricservice.MetricRegistry;
46 import org.openecomp.appc.metricservice.MetricService;
47 import org.openecomp.appc.metricservice.metric.DispatchingFuntionMetric;
48 import org.openecomp.appc.metricservice.metric.Metric;
49 import org.openecomp.appc.metricservice.metric.MetricType;
50 import org.openecomp.appc.metricservice.policy.PublishingPolicy;
51 import org.openecomp.appc.metricservice.publisher.LogPublisher;
52 import org.openecomp.appc.requesthandler.RequestHandler;
53 import org.openecomp.appc.requesthandler.exceptions.*;
54 import org.openecomp.appc.requesthandler.helper.RequestRegistry;
55 import org.openecomp.appc.requesthandler.helper.RequestValidator;
56 import org.openecomp.appc.requesthandler.objects.RequestHandlerInput;
57 import org.openecomp.appc.requesthandler.objects.RequestHandlerOutput;
58 import org.openecomp.appc.transactionrecorder.TransactionRecorder;
59 import org.openecomp.appc.transactionrecorder.objects.TransactionRecord;
60 import org.openecomp.appc.workingstatemanager.WorkingStateManager;
61 import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
62 import com.att.eelf.configuration.EELFLogger;
63 import com.att.eelf.configuration.EELFManager;
64 import com.att.eelf.i18n.EELFResourceManager;
65 import org.openecomp.sdnc.sli.SvcLogicContext;
66 import org.openecomp.sdnc.sli.SvcLogicException;
67 import org.openecomp.sdnc.sli.SvcLogicResource.QueryStatus;
68 import org.openecomp.sdnc.sli.aai.AAIService;
69 import org.osgi.framework.BundleContext;
70 import org.osgi.framework.FrameworkUtil;
71 import org.osgi.framework.ServiceReference;
74 import static com.att.eelf.configuration.Configuration.*;
76 import java.net.InetAddress;
77 import java.util.Date;
78 import java.util.HashMap;
80 import java.util.Properties;
83 * This class provides application logic for the Request/Response Handler Component.
86 public class RequestHandlerImpl implements RequestHandler {
89 * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
91 private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout";
93 private CommandExecutor commandExecutor;
95 private TransactionRecorder transactionRecorder;
96 private MessageAdapter messageAdapter;
97 private RequestValidator requestValidator;
98 private static MetricRegistry metricRegistry;
99 private boolean isMetricEnabled = false;
100 private RequestRegistry requestRegistry;
101 private LockManager lockManager;
102 private WorkingStateManager workingStateManager;
103 private AAIService aaiService;
105 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
107 public void setAaiService(AAIService aaiService) {
108 this.aaiService = aaiService;
111 public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
112 this.transactionRecorder = transactionRecorder;
115 public void setLockManager(LockManager lockManager) {
116 this.lockManager = lockManager;
119 public void setRequestValidator(RequestValidator requestValidator) {
120 this.requestValidator = requestValidator;
123 public void setMessageAdapter(MessageAdapter messageAdapter) {
124 this.messageAdapter = messageAdapter;
127 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
129 public void setWorkingStateManager(WorkingStateManager workingStateManager) {
130 this.workingStateManager = workingStateManager;
133 public RequestHandlerImpl() {
134 requestRegistry = new RequestRegistry();
135 messageAdapter = new MessageAdapterDmaapImpl();
136 messageAdapter.init();
137 Properties properties = configuration.getProperties();
138 if (properties != null && properties.getProperty("metric.enabled") != null) {
139 isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
141 if (isMetricEnabled) {
146 public void setCommandExecutor(CommandExecutor commandExecutor) {
147 this.commandExecutor = commandExecutor;
152 * It receives requests from the north-bound REST API (Communication) Layer and
153 * performs following validations.
154 * 1. VNF exists in A&AI for the given targetID (VnfID)
155 * 2. For the current VNF Orchestration Status, the command can be executed
156 * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
157 * If any of the validation fails, it returns appropriate response
159 * @param input RequestHandlerInput object which contains request header and other request parameters like command , target Id , payload etc.
160 * @return response for request as enum with Return code and message.
163 public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
164 if (logger.isTraceEnabled())
165 logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
166 Params params = null;
167 String vnfId = null, vnfType = null, errorMessage = null;
168 Date startTime = new Date(System.currentTimeMillis());
169 RequestHandlerOutput output = null;
170 setInitialLogProperties(input.getRequestContext());
172 RuntimeContext runtimeContext = new RuntimeContext();
173 runtimeContext.setRequestContext(input.getRequestContext());
174 runtimeContext.setTimeStart(startTime);
175 runtimeContext.setRpcName(input.getRpcName());
177 final ResponseContext responseContext = new ResponseContext();
178 responseContext.setStatus(new Status());
179 responseContext.setAdditionalContext(new HashMap<String, String>(4));
180 responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
181 runtimeContext.setResponseContext(responseContext);
182 runtimeContext.getResponseContext().setStatus(new Status());
184 vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
188 requestValidator.validateRequest(runtimeContext);
190 handleRequest(runtimeContext);
192 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
193 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
194 createTransactionRecord(runtimeContext);
196 output = new RequestHandlerOutput();
197 output.setResponseContext(runtimeContext.getResponseContext());
199 } catch (VNFNotFoundException e) {
200 errorMessage = e.getMessage();
201 String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
202 storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
203 params = new Params().addParam("vnfId", vnfId);
204 output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
205 } catch (NoTransitionDefinedException e) {
206 errorMessage = e.getMessage();
207 String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
208 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
209 output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
210 storeErrorMessageToLog(runtimeContext,
211 LoggingConstants.TargetNames.APPC,
212 LoggingConstants.TargetNames.STATE_MACHINE,
214 } catch (LifecycleException e) {
215 errorMessage = e.getMessage();
216 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
217 output = buildRequestHandlerOutput(LCMCommandStatus.ACTION_NOT_SUPPORTED, params);
218 } catch (UnstableVNFException e) {
219 errorMessage = e.getMessage();
220 params = new Params().addParam("vnfId", vnfId);
221 output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
222 } catch (WorkflowNotFoundException e) {
223 errorMessage = e.getMessage();
224 String vnfTypeVersion = e.vnfTypeVersion;
225 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
226 output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
227 } catch (DGWorkflowNotFoundException e) {
228 errorMessage = e.getMessage();
229 String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
230 storeErrorMessageToLog(runtimeContext,
231 LoggingConstants.TargetNames.APPC,
232 LoggingConstants.TargetNames.WORKFLOW_MANAGER,
234 params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
235 .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
236 output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
237 } catch (RequestExpiredException e) {
238 errorMessage = e.getMessage();
239 params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
240 output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
241 } catch (InvalidInputException e) {
242 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
243 params = new Params().addParam("errorMsg", errorMessage);
244 output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
245 } catch (DuplicateRequestException e) {
246 errorMessage = e.getMessage();
247 output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
248 } catch (Exception e) {
249 storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
250 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
251 params = new Params().addParam("errorMsg", errorMessage);
252 output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
255 if (logger.isDebugEnabled() && errorMessage != null)
256 logger.debug("error occurred in handleRequest " + errorMessage);
257 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
258 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
260 runtimeContext.setResponseContext(output.getResponseContext());
261 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
262 if (isMetricEnabled) {
263 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
265 removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
268 storeAuditLogRecord(runtimeContext);
269 storeMetricLogRecord(runtimeContext);
270 clearRequestLogProperties();
273 if (logger.isTraceEnabled()) {
274 logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
279 private void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
280 LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
281 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
282 runtimeContext.getResponseContext().getStatus() != null ?
283 String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
287 this.getClass().getCanonicalName());
290 private void createTransactionRecord(RuntimeContext runtimeContext) {
291 TransactionRecord transactionRecord = new TransactionRecord();
292 transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
293 transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
294 transactionRecord.setStartTime(runtimeContext.getTimeStart());
295 transactionRecord.setEndTime(new Date(System.currentTimeMillis()));
296 transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
297 transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
298 transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
299 transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
300 transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
301 transactionRecorder.store(transactionRecord);
304 private void handleRequest(RuntimeContext runtimeContext) {
306 switch (runtimeContext.getRequestContext().getAction()) {
309 lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
310 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
311 } catch (LockException e) {
312 Params params = new Params().addParam("errorMsg", e.getMessage());
313 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
314 storeErrorMessageToLog(runtimeContext,
315 LoggingConstants.TargetNames.APPC,
316 LoggingConstants.TargetNames.LOCK_MANAGER,
317 EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
324 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
325 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
326 } catch (LockException e) {
327 //TODO add proper error code and message
328 // logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
329 Params params = new Params().addParam("errorMsg", e.getMessage());
330 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
335 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
336 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
337 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
341 boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
342 runtimeContext.setIsLockAcquired(lockAcquired);
343 callWfOperation(runtimeContext);
344 } catch (LockException e) {
345 Params params = new Params().addParam("errorMsg", e.getMessage());
346 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
348 if (runtimeContext.isLockAcquired()) {
349 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
350 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
352 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
353 //TODO add logger call
354 } catch (LockException e) {
364 private void callWfOperation(RuntimeContext runtimeContext) {
365 int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
366 if (remainingTTL > 0) {
367 if (logger.isDebugEnabled()) {
368 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
371 RuntimeContext clonedContext = cloneContext(runtimeContext);
373 CommandExecutorInput commandExecutorInput = new CommandExecutorInput();
374 commandExecutorInput.setRuntimeContext(clonedContext);
375 commandExecutorInput.setTtl(remainingTTL);
378 commandExecutor.executeCommand(commandExecutorInput);
379 if(logger.isTraceEnabled()) {
380 logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
382 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
383 if (isMetricEnabled) {
384 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
386 } catch (APPCException e) {
387 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
388 Params params = new Params().addParam("errorMsg", errorMessage);
389 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
393 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
394 storeErrorMessageToLog(runtimeContext,
395 LoggingConstants.TargetNames.APPC,
396 LoggingConstants.TargetNames.REQUEST_HANDLER,
397 EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
398 runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
399 runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
400 String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
404 private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
405 runtimeContext.getResponseContext().getStatus().setCode(lcmCommandStatus.getResponseCode());
406 runtimeContext.getResponseContext().getStatus().setMessage(lcmCommandStatus.getFormattedMessage(params));
410 * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
411 * status code and other - depending on DG status). Other properties should not be a problem
413 private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
414 RuntimeContext other = new RuntimeContext();
415 other.setRequestContext(runtimeContext.getRequestContext());
416 other.setResponseContext(new ResponseContext());
417 other.getResponseContext().setStatus(new Status());
418 other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
419 other.setVnfContext(runtimeContext.getVnfContext());
420 other.setRpcName(runtimeContext.getRpcName());
421 other.setTimeStart(runtimeContext.getTimeStart());
422 other.setIsLockAcquired(runtimeContext.isLockAcquired());
427 private void clearRequestLogProperties() {
429 MDC.remove(MDC_KEY_REQUEST_ID);
430 MDC.remove(MDC_SERVICE_INSTANCE_ID);
431 MDC.remove(MDC_SERVICE_NAME);
432 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
433 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
434 } catch (Exception e) {
439 private void removeRequestFromRegistry(CommonHeader commonHeader) {
440 if (logger.isTraceEnabled())
441 logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
442 requestRegistry.removeRequest(
443 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
444 commonHeader.getRequestId(),
445 commonHeader.getSubRequestId()));
448 private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
449 if (logger.isTraceEnabled())
450 logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
451 boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
453 logger.info("Lock acquired for vnfID = " + vnfID);
455 logger.info("vnfID = " + vnfID + " was already locked");
460 private void lockWithTimeout(String vnfId, String requestId) throws LockException {
461 long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
462 acquireVNFLock(vnfId, requestId, timeout);
465 private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
468 releaseVNFLock(vnfId, requestId);
469 } catch (LockException e) {
470 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
474 } else if (resetLockTimeout) {
476 // reset timeout to previous value
477 lockWithTimeout(vnfId, requestId);
478 } catch (LockException e) {
479 logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
484 private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
485 lockManager.releaseLock(vnfId, transactionId);
486 logger.info("Lock released for vnfID = " + vnfId);
489 private void setInitialLogProperties(RequestContext requestContext) {
492 MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
493 if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
494 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
496 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
497 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
499 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
500 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
501 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
502 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
503 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
505 } catch (Exception e) {
506 logger.debug(e.getMessage());
508 } catch (RuntimeException e) {
514 private int calculateRemainingTTL(CommonHeader commonHeader) {
515 if (logger.isTraceEnabled()) {
516 logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
518 long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().getTime());
519 logger.debug("usedTimeInMillis = " + usedTimeInMillis);
520 int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
521 logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
522 Integer inputTTL = this.getInputTTL(commonHeader);
523 logger.debug("inputTTL = " + inputTTL);
524 Integer remainingTTL = inputTTL - usedTimeInSeconds;
525 logger.debug("Remaining TTL = " + remainingTTL);
526 if (logger.isTraceEnabled())
527 logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
531 private Integer getInputTTL(CommonHeader header) {
532 if (logger.isTraceEnabled())
533 logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
534 if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
535 String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
536 Integer defaultTTL = Integer.parseInt(defaultTTLStr);
537 if (logger.isTraceEnabled())
538 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
541 if (logger.isTraceEnabled())
542 logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
544 return header.getFlags().getTtl();
547 private boolean isValidTTL(String ttl) {
548 if (ttl == null || ttl.length() == 0) {
549 if (logger.isTraceEnabled())
550 logger.trace("Exiting from getInputTTL with (result = false)");
554 Integer i = Integer.parseInt(ttl);
556 } catch (NumberFormatException e) {
557 if (logger.isTraceEnabled())
558 logger.trace("Exiting from getInputTTL with (result = false)");
563 private Boolean isLoggingEnabled() {
564 String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
565 Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr);
569 private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
570 RequestHandlerOutput output = new RequestHandlerOutput();
571 ResponseContext responseContext = new ResponseContext();
572 org.openecomp.appc.domainmodel.lcm.Status status = new org.openecomp.appc.domainmodel.lcm.Status();
573 status.setCode(response.getResponseCode());
574 status.setMessage(response.getFormattedMessage(params));
575 responseContext.setStatus(status);
576 output.setResponseContext(responseContext);
581 * This method perform operations required before execution of workflow starts. It retrieves next state for current operation from Lifecycle manager and update it in AAI.
583 * @return true in case AAI updates are successful. false for any error or exception.
586 public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
587 if (logger.isTraceEnabled()) {
588 logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
591 boolean updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
593 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
595 } catch (Exception e) {
596 logger.error("Error updating working state for vnf " + vnfId + e);
597 throw new RuntimeException(e);
600 if (logger.isTraceEnabled())
601 logger.trace("Exiting from onRequestExecutionStart ");
605 * This method perform following operations required after execution of workflow.
606 * It posts asynchronous response to message bus (DMaaP).
608 * Removes request from request registry.
609 * Generate audit logs.
610 * Adds transaction record to database id if transaction logging is enabled.
612 * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
615 public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
616 if (logger.isTraceEnabled()) {
617 logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
620 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
621 requestRegistry.removeRequest(
622 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
623 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
624 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
625 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
626 Status status = runtimeContext.getResponseContext().getStatus();
628 VNFWorkingState workingState;
629 if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
630 workingState = VNFWorkingState.STABLE;
632 workingState = VNFWorkingState.UNKNOWN;
635 UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
636 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
637 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
639 String requestIdentifierString = requestIdentifier.toIdentifierString();
640 workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
643 storeAuditLogRecord(runtimeContext);
645 if (isLoggingEnabled()) {
646 createTransactionRecord(runtimeContext);
650 private void storeAuditLogRecord(RuntimeContext runtimeContext) {
651 LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
652 new Date(System.currentTimeMillis()),
653 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
654 runtimeContext.getResponseContext().getStatus().getMessage(),
655 this.getClass().getCanonicalName());
658 private void storeMetricLogRecord(RuntimeContext runtimeContext) {
659 LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
660 new Date(System.currentTimeMillis()),
661 LoggingConstants.TargetNames.APPC,
662 runtimeContext.getRequestContext().getAction().name(),
663 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
664 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
665 runtimeContext.getResponseContext().getStatus().getMessage(),
666 this.getClass().getCanonicalName());
669 private boolean isReadOnlyAction(VNFOperation action) {
670 return VNFOperation.Sync == action
671 || VNFOperation.Audit == action;
675 //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse
676 private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) {
677 if (logger.isTraceEnabled()) {
678 logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
680 /*boolean updated = updateAsyncResponseStatus(responseContext, isTTLEnd, aaiUpdateSuccess);
682 boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
683 if (!callbackResponse) {
684 logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
686 if (logger.isTraceEnabled())
687 logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
690 //returns true if asyncResponse was modified
691 /* private boolean updateAsyncResponseStatus(ResponseContext asyncResponse, boolean isTTLEnd, boolean aaiUpdateSuccess) {
692 boolean updated = false;
693 if (logger.isTraceEnabled())
694 logger.trace("Entering to updateAsyncResponseStatus with AsyncResponse = "+ObjectUtils.toString(asyncResponse)+ ", isTTLEnd = "+ ObjectUtils.toString(isTTLEnd)+ ", aaiUpdateSuccess = "+ ObjectUtils.toString(aaiUpdateSuccess));
695 if(!aaiUpdateSuccess){
696 if (asyncResponse.getStatus().getCode() == 0 || asyncResponse.getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()) {
697 asyncResponse.getStatus().setCode(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseCode());
698 asyncResponse.getStatus().setMessage(LCMCommandStatus.UPDATE_AAI_FAILURE.getResponseMessage());
702 asyncResponse.getStatus().setCode(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseCode());
703 asyncResponse.getStatus().setMessage(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
706 if (logger.isTraceEnabled())
707 logger.trace("Exiting from updateAsyncResponseStatus with (asyncResponse = "+ ObjectUtils.toString(asyncResponse)+")");
713 * This method perform following operations required if TTL ends when request still waiting in execution queue .
714 * It posts asynchronous response to message bus (DMaaP).
716 * Removes request from request registry.
718 * @param runtimeContext AsyncResponse object which contains VNF Id , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
719 * @param updateAAI boolean flag which indicate AAI upodate status after request completion.
722 public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
723 if (logger.isTraceEnabled()) {
724 logger.trace("Entering to onRequestTTLEnd with " +
725 "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
726 ", updateAAI = " + ObjectUtils.toString(updateAAI));
728 logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
729 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
730 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
731 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
732 requestRegistry.removeRequest(
733 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
734 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
735 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
738 private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
739 String key = "vnf-id = '" + vnf_id + "'";
740 if (logger.isTraceEnabled()) {
741 logger.trace("Entering to getVnfdata with " +
742 "vnfId = " + vnf_id +
743 ", prefix = " + prefix +
744 ", SvcLogicContex = " + ObjectUtils.toString(ctx));
747 QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx);
748 if (QueryStatus.NOT_FOUND.equals(response)) {
749 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
750 } else if (QueryStatus.FAILURE.equals(response)) {
751 throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id);
753 logger.info("AAIResponse: " + response.toString());
754 } catch (SvcLogicException e) {
755 logger.error("Error in getVnfdata " + e);
756 throw new RuntimeException(e);
758 if (logger.isTraceEnabled()) {
759 logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
764 private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
765 if (logger.isTraceEnabled()) {
766 logger.trace("Entering to postVnfdata with " +
767 "vnfId = " + vnf_id +
768 ", status = " + status +
769 ", prefix = " + prefix +
770 ", SvcLogicContext = " + ObjectUtils.toString(ctx));
772 String key = "vnf-id = '" + vnf_id + "'";
773 Map<String, String> data = new HashMap<>();
774 data.put("orchestration-status", status);
776 QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx);
777 if (QueryStatus.NOT_FOUND.equals(response)) {
778 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
780 logger.info("AAIResponse: " + response.toString());
781 if (response.toString().equals("SUCCESS")) {
782 if (logger.isTraceEnabled()) {
783 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")");
788 } catch (SvcLogicException e) {
789 logger.error("Error in postVnfdata " + e);
790 throw new RuntimeException(e);
792 if (logger.isTraceEnabled()) {
793 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
798 private void initMetric() {
799 if (logger.isDebugEnabled())
800 logger.debug("Metric getting initialized");
801 MetricService metricService = getMetricservice();
802 metricRegistry = metricService.createRegistry("APPC");
803 DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
804 dispatchingFunctionCounterBuilder().
805 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
806 withAcceptRequestValue(0)
807 .withRejectRequestValue(0)
809 if (metricRegistry.register(dispatchingFuntionMetric)) {
810 Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
811 LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
812 LogPublisher[] logPublishers = new LogPublisher[1];
813 logPublishers[0] = logPublisher;
814 PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
815 scheduledPolicyBuilder().withPublishers(logPublishers).
816 withMetrics(metrics).
818 if (logger.isDebugEnabled())
819 logger.debug("Policy getting initialized");
820 manuallyScheduledPublishingPolicy.init();
821 if (logger.isDebugEnabled())
822 logger.debug("Metric initialized");
827 private MetricService getMetricservice() {
828 BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
829 ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
831 logger.info("Metric Service from bundlecontext");
832 return (MetricService) bctx.getService(sref);
834 logger.info("Metric Service error from bundlecontext");
835 logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");