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.MessageAdapterImpl;
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 MessageAdapterImpl();
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.INVALID_VNF_STATE, 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 (MissingVNFDataInAAIException e) {
250 params = new Params().addParam("attributeName",e.getMissingAttributeName())
251 .addParam("vnfId",vnfId);
252 output = buildRequestHandlerOutput(LCMCommandStatus.MISSING_VNF_DATA_IN_AAI,params);
253 errorMessage = output.getResponseContext().getStatus().getMessage();
254 } catch (LCMOperationsDisabledException e) {
255 errorMessage = e.getMessage();
256 params = new Params().addParam("errorMsg", errorMessage);
257 output = buildRequestHandlerOutput(LCMCommandStatus.REJECTED, params);
258 } catch (Exception e) {
259 storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
260 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
261 params = new Params().addParam("errorMsg", errorMessage);
262 output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
265 if (logger.isDebugEnabled() && errorMessage != null)
266 logger.debug("error occurred in handleRequest " + errorMessage);
267 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
268 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
270 runtimeContext.setResponseContext(output.getResponseContext());
271 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
272 if (isMetricEnabled) {
273 if((output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode())) {
274 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
276 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
279 removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
282 storeAuditLogRecord(runtimeContext);
283 storeMetricLogRecord(runtimeContext);
284 clearRequestLogProperties();
287 if (logger.isTraceEnabled()) {
288 logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
293 private void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
294 LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
295 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
296 runtimeContext.getResponseContext().getStatus() != null ?
297 String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
301 this.getClass().getCanonicalName());
304 private void createTransactionRecord(RuntimeContext runtimeContext) {
305 TransactionRecord transactionRecord = new TransactionRecord();
306 transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
307 transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
308 transactionRecord.setStartTime(runtimeContext.getTimeStart());
309 transactionRecord.setEndTime(Instant.now());
310 transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
311 transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
312 transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
313 transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
314 transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
315 transactionRecorder.store(transactionRecord);
318 private void handleRequest(RuntimeContext runtimeContext) {
320 switch (runtimeContext.getRequestContext().getAction()) {
323 lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
324 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
325 } catch (LockException e) {
326 Params params = new Params().addParam("errorMsg", e.getMessage());
327 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
328 storeErrorMessageToLog(runtimeContext,
329 LoggingConstants.TargetNames.APPC,
330 LoggingConstants.TargetNames.LOCK_MANAGER,
331 EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
338 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
339 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
340 } catch (LockException e) {
341 //TODO add proper error code and message
342 // logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
343 Params params = new Params().addParam("errorMsg", e.getMessage());
344 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
349 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
350 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
351 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
355 boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
356 runtimeContext.setIsLockAcquired(lockAcquired);
357 callWfOperation(runtimeContext);
358 } catch (LockException e) {
359 Params params = new Params().addParam("errorMsg", e.getMessage());
360 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
362 if (runtimeContext.isLockAcquired()) {
363 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
364 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
366 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
367 //TODO add logger call
368 } catch (LockException e) {
378 private void callWfOperation(RuntimeContext runtimeContext) {
379 int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
380 if (remainingTTL > 0) {
381 if (logger.isDebugEnabled()) {
382 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
385 RuntimeContext commandExecutorInput = cloneContext(runtimeContext);
388 commandExecutor.executeCommand(commandExecutorInput);
389 if(logger.isTraceEnabled()) {
390 logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
392 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
393 if (isMetricEnabled) {
394 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
396 } catch (APPCException e) {
397 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
398 Params params = new Params().addParam("errorMsg", errorMessage);
399 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
403 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
404 storeErrorMessageToLog(runtimeContext,
405 LoggingConstants.TargetNames.APPC,
406 LoggingConstants.TargetNames.REQUEST_HANDLER,
407 EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
408 runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
409 runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
410 String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
414 private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
415 runtimeContext.getResponseContext().setStatus(lcmCommandStatus.toStatus(params));
419 * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
420 * status code and other - depending on DG status). Other properties should not be a problem
422 private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
423 RuntimeContext other = new RuntimeContext();
424 other.setRequestContext(runtimeContext.getRequestContext());
425 other.setResponseContext(new ResponseContext());
426 other.getResponseContext().setStatus(new Status(0, null));
427 other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
428 other.setVnfContext(runtimeContext.getVnfContext());
429 other.setRpcName(runtimeContext.getRpcName());
430 other.setTimeStart(runtimeContext.getTimeStart());
431 other.setIsLockAcquired(runtimeContext.isLockAcquired());
436 private void clearRequestLogProperties() {
438 MDC.remove(MDC_KEY_REQUEST_ID);
439 MDC.remove(MDC_SERVICE_INSTANCE_ID);
440 MDC.remove(MDC_SERVICE_NAME);
441 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
442 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
443 } catch (Exception e) {
448 private void removeRequestFromRegistry(CommonHeader commonHeader) {
449 if (logger.isTraceEnabled())
450 logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
451 requestRegistry.removeRequest(
452 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
453 commonHeader.getRequestId(),
454 commonHeader.getSubRequestId()));
457 private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
458 if (logger.isTraceEnabled())
459 logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
460 boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
462 logger.info("Lock acquired for vnfID = " + vnfID);
464 logger.info("vnfID = " + vnfID + " was already locked");
469 private void lockWithTimeout(String vnfId, String requestId) throws LockException {
470 long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
471 acquireVNFLock(vnfId, requestId, timeout);
474 private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
477 releaseVNFLock(vnfId, requestId);
478 } catch (LockException e) {
479 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
483 } else if (resetLockTimeout) {
485 // reset timeout to previous value
486 lockWithTimeout(vnfId, requestId);
487 } catch (LockException e) {
488 logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
493 private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
494 lockManager.releaseLock(vnfId, transactionId);
495 logger.info("Lock released for vnfID = " + vnfId);
498 private void setInitialLogProperties(RequestContext requestContext) {
501 MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
502 if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
503 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
505 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
506 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
508 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
509 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
510 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
511 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
512 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
514 } catch (Exception e) {
515 logger.debug(e.getMessage());
517 } catch (RuntimeException e) {
523 private int calculateRemainingTTL(CommonHeader commonHeader) {
524 if (logger.isTraceEnabled()) {
525 logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
527 long usedTimeInMillis = ChronoUnit.MILLIS.between(commonHeader.getTimeStamp(), Instant.now());
528 logger.debug("usedTimeInMillis = " + usedTimeInMillis);
529 int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
530 logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
531 Integer inputTTL = this.getInputTTL(commonHeader);
532 logger.debug("inputTTL = " + inputTTL);
533 Integer remainingTTL = inputTTL - usedTimeInSeconds;
534 logger.debug("Remaining TTL = " + remainingTTL);
535 if (logger.isTraceEnabled())
536 logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
540 private Integer getInputTTL(CommonHeader header) {
541 if (logger.isTraceEnabled())
542 logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
543 if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
544 String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
545 Integer defaultTTL = Integer.parseInt(defaultTTLStr);
546 if (logger.isTraceEnabled())
547 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
550 if (logger.isTraceEnabled())
551 logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
553 return header.getFlags().getTtl();
556 private boolean isValidTTL(String ttl) {
557 if (ttl == null || ttl.length() == 0) {
558 if (logger.isTraceEnabled())
559 logger.trace("Exiting from getInputTTL with (result = false)");
563 Integer i = Integer.parseInt(ttl);
565 } catch (NumberFormatException e) {
566 if (logger.isTraceEnabled())
567 logger.trace("Exiting from getInputTTL with (result = false)");
572 private Boolean isLoggingEnabled() {
573 String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
574 Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr);
578 private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
579 RequestHandlerOutput output = new RequestHandlerOutput();
580 ResponseContext responseContext = new ResponseContext();
581 responseContext.setStatus(response.toStatus(params));
582 output.setResponseContext(responseContext);
587 * 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.
589 * @return true in case AAI updates are successful. false for any error or exception.
592 public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
593 if (logger.isTraceEnabled()) {
594 logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
597 if(!readOnlyActivity || !forceFlag || workingStateManager.isVNFStable(vnfId)) {
598 boolean updated = false;
600 updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
601 } catch (Exception e) {
602 logger.error("Error updating working state for vnf " + vnfId + e);
603 throw new RuntimeException(e);
606 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
610 if (logger.isTraceEnabled())
611 logger.trace("Exiting from onRequestExecutionStart ");
615 * This method perform following operations required after execution of workflow.
616 * It posts asynchronous response to message bus (DMaaP).
618 * Removes request from request registry.
619 * Generate audit logs.
620 * Adds transaction record to database id if transaction logging is enabled.
622 * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
625 public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
626 if (logger.isTraceEnabled()) {
627 logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
630 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
631 requestRegistry.removeRequest(
632 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
633 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
634 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
635 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
636 Status status = runtimeContext.getResponseContext().getStatus();
638 VNFWorkingState workingState;
639 if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
640 workingState = VNFWorkingState.STABLE;
642 workingState = VNFWorkingState.UNKNOWN;
645 UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
646 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
647 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
649 String requestIdentifierString = requestIdentifier.toIdentifierString();
650 workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
653 storeAuditLogRecord(runtimeContext);
655 if (isLoggingEnabled()) {
656 createTransactionRecord(runtimeContext);
660 private void storeAuditLogRecord(RuntimeContext runtimeContext) {
661 LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
663 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
664 runtimeContext.getResponseContext().getStatus().getMessage(),
665 this.getClass().getCanonicalName());
668 private void storeMetricLogRecord(RuntimeContext runtimeContext) {
669 LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
671 LoggingConstants.TargetNames.APPC,
672 runtimeContext.getRequestContext().getAction().name(),
673 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
674 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
675 runtimeContext.getResponseContext().getStatus().getMessage(),
676 this.getClass().getCanonicalName());
679 private boolean isReadOnlyAction(VNFOperation action) {
680 return VNFOperation.Sync == action
681 || VNFOperation.Audit == action;
685 //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse
686 private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) {
687 if (logger.isTraceEnabled()) {
688 logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
690 boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
691 if (!callbackResponse) {
692 logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
694 if (logger.isTraceEnabled())
695 logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
699 * This method perform following operations required if TTL ends when request still waiting in execution queue .
700 * It posts asynchronous response to message bus (DMaaP).
702 * Removes request from request registry.
704 * @param runtimeContext AsyncResponse object which contains VNF Id , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
705 * @param updateAAI boolean flag which indicate AAI upodate status after request completion.
708 public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
709 if (logger.isTraceEnabled()) {
710 logger.trace("Entering to onRequestTTLEnd with " +
711 "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
712 ", updateAAI = " + ObjectUtils.toString(updateAAI));
714 logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
715 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
716 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
717 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
718 requestRegistry.removeRequest(
719 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
720 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
721 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
724 private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
725 String key = "vnf-id = '" + vnf_id + "'";
726 if (logger.isTraceEnabled()) {
727 logger.trace("Entering to getVnfdata with " +
728 "vnfId = " + vnf_id +
729 ", prefix = " + prefix +
730 ", SvcLogicContex = " + ObjectUtils.toString(ctx));
733 QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx);
734 if (QueryStatus.NOT_FOUND.equals(response)) {
735 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
736 } else if (QueryStatus.FAILURE.equals(response)) {
737 throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id);
739 logger.info("AAIResponse: " + response.toString());
740 } catch (SvcLogicException e) {
741 logger.error("Error in getVnfdata " + e);
742 throw new RuntimeException(e);
744 if (logger.isTraceEnabled()) {
745 logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
750 private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
751 if (logger.isTraceEnabled()) {
752 logger.trace("Entering to postVnfdata with " +
753 "vnfId = " + vnf_id +
754 ", status = " + status +
755 ", prefix = " + prefix +
756 ", SvcLogicContext = " + ObjectUtils.toString(ctx));
758 String key = "vnf-id = '" + vnf_id + "'";
759 Map<String, String> data = new HashMap<>();
760 data.put("orchestration-status", status);
762 QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx);
763 if (QueryStatus.NOT_FOUND.equals(response)) {
764 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
766 logger.info("AAIResponse: " + response.toString());
767 if (response.toString().equals("SUCCESS")) {
768 if (logger.isTraceEnabled()) {
769 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")");
774 } catch (SvcLogicException e) {
775 logger.error("Error in postVnfdata " + e);
776 throw new RuntimeException(e);
778 if (logger.isTraceEnabled()) {
779 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
784 private void initMetric() {
785 if (logger.isDebugEnabled())
786 logger.debug("Metric getting initialized");
787 MetricService metricService = getMetricservice();
788 metricRegistry = metricService.createRegistry("APPC");
789 DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
790 dispatchingFunctionCounterBuilder().
791 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
792 withAcceptRequestValue(0)
793 .withRejectRequestValue(0)
795 if (metricRegistry.register(dispatchingFuntionMetric)) {
796 Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
797 LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
798 LogPublisher[] logPublishers = new LogPublisher[1];
799 logPublishers[0] = logPublisher;
800 PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
801 scheduledPolicyBuilder().withPublishers(logPublishers).
802 withMetrics(metrics).
804 if (logger.isDebugEnabled())
805 logger.debug("Policy getting initialized");
806 manuallyScheduledPublishingPolicy.init();
807 if (logger.isDebugEnabled())
808 logger.debug("Metric initialized");
813 private MetricService getMetricservice() {
814 BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
815 ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
817 logger.info("Metric Service from bundlecontext");
818 return (MetricService) bctx.getService(sref);
820 logger.info("Metric Service error from bundlecontext");
821 logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");
827 * This method returns the count of in progress requests
828 * * @return in progress requests count
831 public int getInprogressRequestCount() {
832 if (logger.isTraceEnabled()) {
833 logger.trace("Entering to getInprogressRequestCount");
835 return requestRegistry.getRegisteredRequestCount();