2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Copyright (C) 2017 Amdocs
8 * =============================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 * ============LICENSE_END=========================================================
25 package org.openecomp.appc.requesthandler.impl;
27 import org.apache.commons.lang.ObjectUtils;
28 import org.openecomp.appc.common.constant.Constants;
29 import org.openecomp.appc.configuration.Configuration;
30 import org.openecomp.appc.configuration.ConfigurationFactory;
31 import org.openecomp.appc.domainmodel.lcm.*;
32 import org.openecomp.appc.exceptions.APPCException;
33 import org.openecomp.appc.executor.CommandExecutor;
34 import org.openecomp.appc.executor.UnstableVNFException;
35 import org.openecomp.appc.executor.objects.LCMCommandStatus;
36 import org.openecomp.appc.executor.objects.Params;
37 import org.openecomp.appc.executor.objects.UniqueRequestIdentifier;
38 import org.openecomp.appc.i18n.Msg;
39 import org.openecomp.appc.lifecyclemanager.objects.LifecycleException;
40 import org.openecomp.appc.lifecyclemanager.objects.NoTransitionDefinedException;
41 import org.openecomp.appc.lockmanager.api.LockException;
42 import org.openecomp.appc.lockmanager.api.LockManager;
43 import org.openecomp.appc.logging.LoggingConstants;
44 import org.openecomp.appc.logging.LoggingUtils;
45 import org.openecomp.appc.messageadapter.MessageAdapter;
46 import org.openecomp.appc.messageadapter.impl.MessageAdapterImpl;
47 import org.openecomp.appc.metricservice.MetricRegistry;
48 import org.openecomp.appc.metricservice.MetricService;
49 import org.openecomp.appc.metricservice.metric.DispatchingFuntionMetric;
50 import org.openecomp.appc.metricservice.metric.Metric;
51 import org.openecomp.appc.metricservice.metric.MetricType;
52 import org.openecomp.appc.metricservice.policy.PublishingPolicy;
53 import org.openecomp.appc.metricservice.publisher.LogPublisher;
54 import org.openecomp.appc.requesthandler.RequestHandler;
55 import org.openecomp.appc.requesthandler.exceptions.*;
56 import org.openecomp.appc.requesthandler.helper.RequestRegistry;
57 import org.openecomp.appc.requesthandler.helper.RequestValidator;
58 import org.openecomp.appc.requesthandler.objects.RequestHandlerInput;
59 import org.openecomp.appc.requesthandler.objects.RequestHandlerOutput;
60 import org.openecomp.appc.transactionrecorder.TransactionRecorder;
61 import org.openecomp.appc.transactionrecorder.objects.TransactionRecord;
62 import org.openecomp.appc.workingstatemanager.WorkingStateManager;
63 import org.openecomp.appc.workingstatemanager.objects.VNFWorkingState;
64 import com.att.eelf.configuration.EELFLogger;
65 import com.att.eelf.configuration.EELFManager;
66 import com.att.eelf.i18n.EELFResourceManager;
67 import org.openecomp.sdnc.sli.SvcLogicContext;
68 import org.openecomp.sdnc.sli.SvcLogicException;
69 import org.openecomp.sdnc.sli.SvcLogicResource.QueryStatus;
70 import org.openecomp.sdnc.sli.aai.AAIService;
71 import org.osgi.framework.BundleContext;
72 import org.osgi.framework.FrameworkUtil;
73 import org.osgi.framework.ServiceReference;
76 import static com.att.eelf.configuration.Configuration.*;
78 import java.net.InetAddress;
79 import java.time.Instant;
80 import java.time.temporal.ChronoUnit;
81 import java.util.Date;
82 import java.util.HashMap;
84 import java.util.Properties;
87 * This class provides application logic for the Request/Response Handler Component.
90 public class RequestHandlerImpl implements RequestHandler {
93 * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
95 private static final String PROP_IDLE_TIMEOUT = "org.openecomp.appc.lock.idleTimeout";
97 private CommandExecutor commandExecutor;
99 private TransactionRecorder transactionRecorder;
100 private MessageAdapter messageAdapter;
101 private RequestValidator requestValidator;
102 private static MetricRegistry metricRegistry;
103 private boolean isMetricEnabled = false;
104 private RequestRegistry requestRegistry;
105 private LockManager lockManager;
106 private WorkingStateManager workingStateManager;
107 private AAIService aaiService;
109 private static final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
111 public void setAaiService(AAIService aaiService) {
112 this.aaiService = aaiService;
115 public void setTransactionRecorder(TransactionRecorder transactionRecorder) {
116 this.transactionRecorder = transactionRecorder;
119 public void setLockManager(LockManager lockManager) {
120 this.lockManager = lockManager;
123 public void setRequestValidator(RequestValidator requestValidator) {
124 this.requestValidator = requestValidator;
127 public void setMessageAdapter(MessageAdapter messageAdapter) {
128 this.messageAdapter = messageAdapter;
131 private static final Configuration configuration = ConfigurationFactory.getConfiguration();
133 public void setWorkingStateManager(WorkingStateManager workingStateManager) {
134 this.workingStateManager = workingStateManager;
137 public RequestHandlerImpl() {
138 requestRegistry = new RequestRegistry();
139 messageAdapter = new MessageAdapterImpl();
140 messageAdapter.init();
141 Properties properties = configuration.getProperties();
142 if (properties != null && properties.getProperty("metric.enabled") != null) {
143 isMetricEnabled = Boolean.valueOf(properties.getProperty("metric.enabled"));
145 if (isMetricEnabled) {
150 public void setCommandExecutor(CommandExecutor commandExecutor) {
151 this.commandExecutor = commandExecutor;
156 * It receives requests from the north-bound REST API (Communication) Layer and
157 * performs following validations.
158 * 1. VNF exists in A&AI for the given targetID (VnfID)
159 * 2. For the current VNF Orchestration Status, the command can be executed
160 * 3. For the given VNF type and Operation, there exists work-flow definition in the APPC database
161 * If any of the validation fails, it returns appropriate response
163 * @param input RequestHandlerInput object which contains request header and other request parameters like command , target Id , payload etc.
164 * @return response for request as enum with Return code and message.
167 public RequestHandlerOutput handleRequest(RequestHandlerInput input) {
168 if (logger.isTraceEnabled())
169 logger.trace("Entering to handleRequest with RequestHandlerInput = " + ObjectUtils.toString(input) + ")");
170 Params params = null;
171 String vnfId = null, vnfType = null, errorMessage = null;
172 Instant startTime = Instant.now();
173 RequestHandlerOutput output = null;
174 setInitialLogProperties(input.getRequestContext());
176 RuntimeContext runtimeContext = new RuntimeContext();
177 runtimeContext.setRequestContext(input.getRequestContext());
178 runtimeContext.setTimeStart(startTime);
179 runtimeContext.setRpcName(input.getRpcName());
181 final ResponseContext responseContext = new ResponseContext();
182 responseContext.setStatus(new Status(0, null));
183 responseContext.setAdditionalContext(new HashMap<String, String>(4));
184 responseContext.setCommonHeader(input.getRequestContext().getCommonHeader());
185 runtimeContext.setResponseContext(responseContext);
186 runtimeContext.getResponseContext().setStatus(new Status(0, null));
188 vnfId = runtimeContext.getRequestContext().getActionIdentifiers().getVnfId();
192 requestValidator.validateRequest(runtimeContext);
194 handleRequest(runtimeContext);
196 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
197 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
198 createTransactionRecord(runtimeContext);
200 output = new RequestHandlerOutput();
201 output.setResponseContext(runtimeContext.getResponseContext());
203 } catch (VNFNotFoundException e) {
204 errorMessage = e.getMessage();
205 String logMessage = EELFResourceManager.format(Msg.APPC_NO_RESOURCE_FOUND, vnfId);
206 storeErrorMessageToLog(runtimeContext, LoggingConstants.TargetNames.AAI, "", logMessage);
207 params = new Params().addParam("vnfId", vnfId);
208 output = buildRequestHandlerOutput(LCMCommandStatus.VNF_NOT_FOUND, params);
209 } catch (NoTransitionDefinedException e) {
210 errorMessage = e.getMessage();
211 String logMessage = EELFResourceManager.format(Msg.VF_UNDEFINED_STATE, input.getRequestContext().getCommonHeader().getOriginatorId(), input.getRequestContext().getAction().name());
212 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
213 output = buildRequestHandlerOutput(LCMCommandStatus.NO_TRANSITION_DEFINE, params);
214 storeErrorMessageToLog(runtimeContext,
215 LoggingConstants.TargetNames.APPC,
216 LoggingConstants.TargetNames.STATE_MACHINE,
218 } catch (LifecycleException e) {
219 errorMessage = e.getMessage();
220 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("currentState", e.currentState);
221 output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_VNF_STATE, params);
222 } catch (UnstableVNFException e) {
223 errorMessage = e.getMessage();
224 params = new Params().addParam("vnfId", vnfId);
225 output = buildRequestHandlerOutput(LCMCommandStatus.UNSTABLE_VNF, params);
226 } catch (WorkflowNotFoundException e) {
227 errorMessage = e.getMessage();
228 String vnfTypeVersion = e.vnfTypeVersion;
229 params = new Params().addParam("actionName", input.getRequestContext().getAction()).addParam("vnfTypeVersion", vnfTypeVersion);
230 output = buildRequestHandlerOutput(LCMCommandStatus.WORKFLOW_NOT_FOUND, params);
231 } catch (DGWorkflowNotFoundException e) {
232 errorMessage = e.getMessage();
233 String logMessage = EELFResourceManager.format(Msg.APPC_WORKFLOW_NOT_FOUND, vnfType, input.getRequestContext().getAction().name());
234 storeErrorMessageToLog(runtimeContext,
235 LoggingConstants.TargetNames.APPC,
236 LoggingConstants.TargetNames.WORKFLOW_MANAGER,
238 params = new Params().addParam("actionName", input.getRequestContext().getAction().name())
239 .addParam("dgModule", e.workflowModule).addParam("dgName", e.workflowName).addParam("dgVersion", e.workflowVersion);
240 output = buildRequestHandlerOutput(LCMCommandStatus.DG_WORKFLOW_NOT_FOUND, params);
241 } catch (RequestExpiredException e) {
242 errorMessage = e.getMessage();
243 params = new Params().addParam("actionName", input.getRequestContext().getAction().name());
244 output = buildRequestHandlerOutput(LCMCommandStatus.EXPIRED_REQUEST, params);
245 } catch (InvalidInputException e) {
246 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
247 params = new Params().addParam("errorMsg", errorMessage);
248 output = buildRequestHandlerOutput(LCMCommandStatus.INVALID_INPUT_PARAMETER, params);
249 } catch (DuplicateRequestException e) {
250 errorMessage = e.getMessage();
251 output = buildRequestHandlerOutput(LCMCommandStatus.DUPLICATE_REQUEST, null);
252 } catch (MissingVNFDataInAAIException e) {
253 params = new Params().addParam("attributeName",e.getMissingAttributeName())
254 .addParam("vnfId",vnfId);
255 output = buildRequestHandlerOutput(LCMCommandStatus.MISSING_VNF_DATA_IN_AAI,params);
256 errorMessage = output.getResponseContext().getStatus().getMessage();
257 } catch (LCMOperationsDisabledException e) {
258 errorMessage = e.getMessage();
259 params = new Params().addParam("errorMsg", errorMessage);
260 output = buildRequestHandlerOutput(LCMCommandStatus.REJECTED, params);
261 } catch (Exception e) {
262 storeErrorMessageToLog(runtimeContext, "", "", "Exception = " + e.getMessage());
263 errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
264 params = new Params().addParam("errorMsg", errorMessage);
265 output = buildRequestHandlerOutput(LCMCommandStatus.UNEXPECTED_ERROR, params);
268 if (logger.isDebugEnabled() && errorMessage != null)
269 logger.debug("error occurred in handleRequest " + errorMessage);
270 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.ACCEPTED.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode()));
271 logger.debug("output.getResponse().getResponseCode().equals(LCMCommandStatus.SUCCESS.getResponseCode(): " + (output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode()));
273 runtimeContext.setResponseContext(output.getResponseContext());
274 if ((null == output) || !(output.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode())) {
275 if (isMetricEnabled) {
276 if((output.getResponseContext().getStatus().getCode() == LCMCommandStatus.SUCCESS.getResponseCode())) {
277 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
279 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementRejectedRequest();
282 removeRequestFromRegistry(input.getRequestContext().getCommonHeader());
285 storeAuditLogRecord(runtimeContext);
286 storeMetricLogRecord(runtimeContext);
287 clearRequestLogProperties();
290 if (logger.isTraceEnabled()) {
291 logger.trace("Exiting from handleRequest with (RequestHandlerOutput = " + ObjectUtils.toString(output.getResponseContext()) + ")");
296 private void storeErrorMessageToLog(RuntimeContext runtimeContext, String targetEntity, String targetServiceName, String additionalMessage) {
297 LoggingUtils.logErrorMessage(runtimeContext.getResponseContext().getStatus() != null ?
298 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()) : "",
299 runtimeContext.getResponseContext().getStatus() != null ?
300 String.valueOf(runtimeContext.getResponseContext().getStatus().getMessage()) : "",
304 this.getClass().getCanonicalName());
307 private void createTransactionRecord(RuntimeContext runtimeContext) {
308 TransactionRecord transactionRecord = new TransactionRecord();
309 transactionRecord.setTimeStamp(runtimeContext.getResponseContext().getCommonHeader().getTimeStamp());
310 transactionRecord.setRequestID(runtimeContext.getResponseContext().getCommonHeader().getRequestId());
311 transactionRecord.setStartTime(runtimeContext.getTimeStart());
312 transactionRecord.setEndTime(Instant.now());
313 transactionRecord.setTargetID(runtimeContext.getVnfContext().getId());
314 transactionRecord.setTargetType(runtimeContext.getVnfContext().getType());
315 transactionRecord.setOperation(runtimeContext.getRequestContext().getAction().name());
316 transactionRecord.setResultCode(String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()));
317 transactionRecord.setDescription(runtimeContext.getResponseContext().getStatus().getMessage());
318 transactionRecorder.store(transactionRecord);
321 private void handleRequest(RuntimeContext runtimeContext) {
323 switch (runtimeContext.getRequestContext().getAction()) {
326 lockWithTimeout(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
327 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
328 } catch (LockException e) {
329 Params params = new Params().addParam("errorMsg", e.getMessage());
330 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
331 storeErrorMessageToLog(runtimeContext,
332 LoggingConstants.TargetNames.APPC,
333 LoggingConstants.TargetNames.LOCK_MANAGER,
334 EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
341 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
342 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
343 } catch (LockException e) {
344 //TODO add proper error code and message
345 // logger.error(EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
346 Params params = new Params().addParam("errorMsg", e.getMessage());
347 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
352 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
353 fillStatus(runtimeContext,LCMCommandStatus.SUCCESS, null);
354 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
358 boolean lockAcquired = acquireVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), 0);
359 runtimeContext.setIsLockAcquired(lockAcquired);
360 callWfOperation(runtimeContext);
361 } catch (LockException e) {
362 Params params = new Params().addParam("errorMsg", e.getMessage());
363 fillStatus(runtimeContext, LCMCommandStatus.LOCKING_FAILURE, params);
365 if (runtimeContext.isLockAcquired()) {
366 final int statusCode = runtimeContext.getResponseContext().getStatus().getCode();
367 if (statusCode % 100 == 2 || statusCode % 100 == 3) {
369 releaseVNFLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
370 //TODO add logger call
371 } catch (LockException e) {
381 private void callWfOperation(RuntimeContext runtimeContext) {
382 int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
383 if (remainingTTL > 0) {
384 if (logger.isDebugEnabled()) {
385 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
388 RuntimeContext commandExecutorInput = cloneContext(runtimeContext);
391 commandExecutor.executeCommand(commandExecutorInput);
392 if(logger.isTraceEnabled()) {
393 logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
395 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
396 if (isMetricEnabled) {
397 ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
399 } catch (APPCException e) {
400 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
401 Params params = new Params().addParam("errorMsg", errorMessage);
402 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
406 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
407 storeErrorMessageToLog(runtimeContext,
408 LoggingConstants.TargetNames.APPC,
409 LoggingConstants.TargetNames.REQUEST_HANDLER,
410 EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
411 runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
412 runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
413 String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
417 private void fillStatus(RuntimeContext runtimeContext, LCMCommandStatus lcmCommandStatus, Params params) {
418 runtimeContext.getResponseContext().setStatus(lcmCommandStatus.toStatus(params));
422 * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
423 * status code and other - depending on DG status). Other properties should not be a problem
425 private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
426 RuntimeContext other = new RuntimeContext();
427 other.setRequestContext(runtimeContext.getRequestContext());
428 other.setResponseContext(new ResponseContext());
429 other.getResponseContext().setStatus(new Status(0, null));
430 other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
431 other.setVnfContext(runtimeContext.getVnfContext());
432 other.setRpcName(runtimeContext.getRpcName());
433 other.setTimeStart(runtimeContext.getTimeStart());
434 other.setIsLockAcquired(runtimeContext.isLockAcquired());
439 private void clearRequestLogProperties() {
441 MDC.remove(MDC_KEY_REQUEST_ID);
442 MDC.remove(MDC_SERVICE_INSTANCE_ID);
443 MDC.remove(MDC_SERVICE_NAME);
444 MDC.remove(LoggingConstants.MDCKeys.PARTNER_NAME);
445 MDC.remove(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY);
446 } catch (Exception e) {
451 private void removeRequestFromRegistry(CommonHeader commonHeader) {
452 if (logger.isTraceEnabled())
453 logger.trace("Entering to removeRequestFromRegistry with RequestHeader = " + ObjectUtils.toString(commonHeader));
454 requestRegistry.removeRequest(
455 new UniqueRequestIdentifier(commonHeader.getOriginatorId(),
456 commonHeader.getRequestId(),
457 commonHeader.getSubRequestId()));
460 private boolean acquireVNFLock(String vnfID, String requestId, long timeout) throws LockException {
461 if (logger.isTraceEnabled())
462 logger.trace("Entering to acquireVNFLock with vnfID = " + vnfID);
463 boolean lockAcquired = lockManager.acquireLock(vnfID, requestId, timeout);
465 logger.info("Lock acquired for vnfID = " + vnfID);
467 logger.info("vnfID = " + vnfID + " was already locked");
472 private void lockWithTimeout(String vnfId, String requestId) throws LockException {
473 long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
474 acquireVNFLock(vnfId, requestId, timeout);
477 private void resetLock(String vnfId, String requestId, boolean lockAcquired, boolean resetLockTimeout) {
480 releaseVNFLock(vnfId, requestId);
481 } catch (LockException e) {
482 logger.error("Unlock VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
486 } else if (resetLockTimeout) {
488 // reset timeout to previous value
489 lockWithTimeout(vnfId, requestId);
490 } catch (LockException e) {
491 logger.error("Reset lock idle timeout for VNF [" + vnfId + "] failed. Request id: [" + requestId + "]", e);
496 private void releaseVNFLock(String vnfId, String transactionId) throws LockException {
497 lockManager.releaseLock(vnfId, transactionId);
498 logger.info("Lock released for vnfID = " + vnfId);
501 private void setInitialLogProperties(RequestContext requestContext) {
504 MDC.put(MDC_KEY_REQUEST_ID, requestContext.getCommonHeader().getRequestId());
505 if (requestContext.getActionIdentifiers().getServiceInstanceId() != null) {
506 MDC.put(MDC_SERVICE_INSTANCE_ID, requestContext.getActionIdentifiers().getServiceInstanceId());
508 MDC.put(LoggingConstants.MDCKeys.PARTNER_NAME, requestContext.getCommonHeader().getOriginatorId());
509 MDC.put(MDC_INSTANCE_UUID, ""); // value should be created in the future
511 MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getCanonicalHostName()); //Don't change it to a .getHostName() again please. It's wrong!
512 MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress());
513 MDC.put(LoggingConstants.MDCKeys.SERVER_NAME, InetAddress.getLocalHost().getHostName());
514 MDC.put(MDC_SERVICE_NAME, requestContext.getAction().name());
515 MDC.put(LoggingConstants.MDCKeys.TARGET_VIRTUAL_ENTITY, requestContext.getActionIdentifiers().getVnfId());
517 } catch (Exception e) {
518 logger.debug(e.getMessage());
520 } catch (RuntimeException e) {
526 private int calculateRemainingTTL(CommonHeader commonHeader) {
527 if (logger.isTraceEnabled()) {
528 logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
530 long usedTimeInMillis = ChronoUnit.MILLIS.between(commonHeader.getTimeStamp(), Instant.now());
531 logger.debug("usedTimeInMillis = " + usedTimeInMillis);
532 int usedTimeInSeconds = Math.round(usedTimeInMillis / 1000);
533 logger.debug("usedTimeInSeconds = " + usedTimeInSeconds);
534 Integer inputTTL = this.getInputTTL(commonHeader);
535 logger.debug("inputTTL = " + inputTTL);
536 Integer remainingTTL = inputTTL - usedTimeInSeconds;
537 logger.debug("Remaining TTL = " + remainingTTL);
538 if (logger.isTraceEnabled())
539 logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
543 private Integer getInputTTL(CommonHeader header) {
544 if (logger.isTraceEnabled())
545 logger.trace("Entering in getInputTTL with RequestHeader = " + ObjectUtils.toString(header));
546 if (!isValidTTL(String.valueOf(header.getFlags().getTtl()))) {
547 String defaultTTLStr = configuration.getProperty("org.openecomp.appc.workflow.default.ttl", String.valueOf(Constants.DEFAULT_TTL));
548 Integer defaultTTL = Integer.parseInt(defaultTTLStr);
549 if (logger.isTraceEnabled())
550 logger.trace("Exiting from getInputTTL with (defaultTTL = " + ObjectUtils.toString(defaultTTL) + ")");
553 if (logger.isTraceEnabled())
554 logger.trace("Exiting from getInputTTL with (inputTTL = " + ObjectUtils.toString(header.getFlags().getTtl()) + ")");
556 return header.getFlags().getTtl();
559 private boolean isValidTTL(String ttl) {
560 if (ttl == null || ttl.length() == 0) {
561 if (logger.isTraceEnabled())
562 logger.trace("Exiting from getInputTTL with (result = false)");
566 Integer i = Integer.parseInt(ttl);
568 } catch (NumberFormatException e) {
569 if (logger.isTraceEnabled())
570 logger.trace("Exiting from getInputTTL with (result = false)");
575 private Boolean isLoggingEnabled() {
576 String defaultFlagStr = configuration.getProperty("org.openecomp.appc.localTransactionRecorder.enable", String.valueOf(Constants.DEFAULT_LOGGING_FLAG));
577 Boolean defaultFlag = Boolean.parseBoolean(defaultFlagStr);
581 private static RequestHandlerOutput buildRequestHandlerOutput(LCMCommandStatus response, Params params) {
582 RequestHandlerOutput output = new RequestHandlerOutput();
583 ResponseContext responseContext = new ResponseContext();
584 responseContext.setStatus(response.toStatus(params));
585 output.setResponseContext(responseContext);
590 * 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.
592 * @return true in case AAI updates are successful. false for any error or exception.
595 public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, String requestIdentifierString, boolean forceFlag) throws UnstableVNFException {
596 if (logger.isTraceEnabled()) {
597 logger.trace("Entering to onRequestExecutionStart with vnfId = " + vnfId + "and requestIdentifierString = " + requestIdentifierString);
600 if(!readOnlyActivity || !forceFlag || workingStateManager.isVNFStable(vnfId)) {
601 boolean updated = false;
603 updated = workingStateManager.setWorkingState(vnfId, VNFWorkingState.UNSTABLE, requestIdentifierString, forceFlag);
604 } catch (Exception e) {
605 logger.error("Error updating working state for vnf " + vnfId + e);
606 throw new RuntimeException(e);
609 throw new UnstableVNFException("VNF is not stable for vnfID = " + vnfId);
613 if (logger.isTraceEnabled())
614 logger.trace("Exiting from onRequestExecutionStart ");
618 * This method perform following operations required after execution of workflow.
619 * It posts asynchronous response to message bus (DMaaP).
621 * Removes request from request registry.
622 * Generate audit logs.
623 * Adds transaction record to database id if transaction logging is enabled.
625 * @param isAAIUpdated boolean flag which indicate AAI upodate status after request completion.
628 public void onRequestExecutionEnd(RuntimeContext runtimeContext, boolean isAAIUpdated) {
629 if (logger.isTraceEnabled()) {
630 logger.trace("Entering to onRequestExecutionEnd with runtimeContext = " + ObjectUtils.toString(runtimeContext));
633 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
634 requestRegistry.removeRequest(
635 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
636 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
637 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
638 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
639 Status status = runtimeContext.getResponseContext().getStatus();
641 VNFWorkingState workingState;
642 if (status.getCode() == LCMCommandStatus.SUCCESS.getResponseCode() || isReadOnlyAction(runtimeContext.getRequestContext().getAction())) {
643 workingState = VNFWorkingState.STABLE;
645 workingState = VNFWorkingState.UNKNOWN;
648 UniqueRequestIdentifier requestIdentifier = new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
649 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
650 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId());
652 String requestIdentifierString = requestIdentifier.toIdentifierString();
653 workingStateManager.setWorkingState(runtimeContext.getVnfContext().getId(), workingState, requestIdentifierString, false);
656 storeAuditLogRecord(runtimeContext);
658 if (isLoggingEnabled()) {
659 createTransactionRecord(runtimeContext);
663 private void storeAuditLogRecord(RuntimeContext runtimeContext) {
664 LoggingUtils.logAuditMessage(runtimeContext.getTimeStart(),
666 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
667 runtimeContext.getResponseContext().getStatus().getMessage(),
668 this.getClass().getCanonicalName());
671 private void storeMetricLogRecord(RuntimeContext runtimeContext) {
672 LoggingUtils.logMetricsMessage(runtimeContext.getTimeStart(),
674 LoggingConstants.TargetNames.APPC,
675 runtimeContext.getRequestContext().getAction().name(),
676 runtimeContext.getResponseContext().getStatus().getCode() == LCMCommandStatus.ACCEPTED.getResponseCode() ? LoggingConstants.StatusCodes.COMPLETE : LoggingConstants.StatusCodes.ERROR,
677 String.valueOf(runtimeContext.getResponseContext().getStatus().getCode()),
678 runtimeContext.getResponseContext().getStatus().getMessage(),
679 this.getClass().getCanonicalName());
682 private boolean isReadOnlyAction(VNFOperation action) {
683 return VNFOperation.Sync == action
684 || VNFOperation.Audit == action;
688 //returns null if asyncResponse was not modified otherwise reutrns the updated asyncResponse
689 private void postMessageToDMaaP(VNFOperation operation, String rpcName, ResponseContext responseContext/*, boolean isTTLEnd, boolean aaiUpdateSuccess*/) {
690 if (logger.isTraceEnabled()) {
691 logger.trace("Entering to postMessageToDMaaP with AsyncResponse = " + ObjectUtils.toString(responseContext));
693 boolean callbackResponse = messageAdapter.post(operation, rpcName, responseContext);
694 if (!callbackResponse) {
695 logger.error("DMaaP posting status: " + callbackResponse, "dmaapMessage: " + responseContext);
697 if (logger.isTraceEnabled())
698 logger.trace("Exiting from postMessageToDMaaP with (callbackResponse = " + ObjectUtils.toString(callbackResponse) + ")");
702 * This method perform following operations required if TTL ends when request still waiting in execution queue .
703 * It posts asynchronous response to message bus (DMaaP).
705 * Removes request from request registry.
707 * @param runtimeContext AsyncResponse object which contains VNF Id , timestamp , apiVersion, responseId, executionSuccess, payload, isExpired, action, startTime, vnfType, originatorId, subResponseId;
708 * @param updateAAI boolean flag which indicate AAI upodate status after request completion.
711 public void onRequestTTLEnd(RuntimeContext runtimeContext, boolean updateAAI) {
712 if (logger.isTraceEnabled()) {
713 logger.trace("Entering to onRequestTTLEnd with " +
714 "AsyncResponse = " + ObjectUtils.toString(runtimeContext) +
715 ", updateAAI = " + ObjectUtils.toString(updateAAI));
717 logger.error(LCMCommandStatus.EXPIRED_REQUEST_FAILURE.getResponseMessage());
718 fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST_FAILURE, null);
719 postMessageToDMaaP(runtimeContext.getRequestContext().getAction(), runtimeContext.getRpcName(), runtimeContext.getResponseContext());
720 resetLock(runtimeContext.getVnfContext().getId(), runtimeContext.getResponseContext().getCommonHeader().getRequestId(), runtimeContext.isLockAcquired(), true);
721 requestRegistry.removeRequest(
722 new UniqueRequestIdentifier(runtimeContext.getResponseContext().getCommonHeader().getOriginatorId(),
723 runtimeContext.getResponseContext().getCommonHeader().getRequestId(),
724 runtimeContext.getResponseContext().getCommonHeader().getSubRequestId()));
727 private SvcLogicContext getVnfdata(String vnf_id, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
728 String key = "vnf-id = '" + vnf_id + "'";
729 if (logger.isTraceEnabled()) {
730 logger.trace("Entering to getVnfdata with " +
731 "vnfId = " + vnf_id +
732 ", prefix = " + prefix +
733 ", SvcLogicContex = " + ObjectUtils.toString(ctx));
736 QueryStatus response = aaiService.query("generic-vnf", false, null, key, prefix, null, ctx);
737 if (QueryStatus.NOT_FOUND.equals(response)) {
738 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
739 } else if (QueryStatus.FAILURE.equals(response)) {
740 throw new RuntimeException("Error Querying AAI with vnfID = " + vnf_id);
742 logger.info("AAIResponse: " + response.toString());
743 } catch (SvcLogicException e) {
744 logger.error("Error in getVnfdata " + e);
745 throw new RuntimeException(e);
747 if (logger.isTraceEnabled()) {
748 logger.trace("Exiting from getVnfdata with (SvcLogicContext = " + ObjectUtils.toString(ctx) + ")");
753 private boolean postVnfdata(String vnf_id, String status, String prefix, SvcLogicContext ctx) throws VNFNotFoundException {
754 if (logger.isTraceEnabled()) {
755 logger.trace("Entering to postVnfdata with " +
756 "vnfId = " + vnf_id +
757 ", status = " + status +
758 ", prefix = " + prefix +
759 ", SvcLogicContext = " + ObjectUtils.toString(ctx));
761 String key = "vnf-id = '" + vnf_id + "'";
762 Map<String, String> data = new HashMap<>();
763 data.put("orchestration-status", status);
765 QueryStatus response = aaiService.update("generic-vnf", key, data, prefix, ctx);
766 if (QueryStatus.NOT_FOUND.equals(response)) {
767 throw new VNFNotFoundException("VNF not found for vnf_id = " + vnf_id);
769 logger.info("AAIResponse: " + response.toString());
770 if (response.toString().equals("SUCCESS")) {
771 if (logger.isTraceEnabled()) {
772 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(true) + ")");
777 } catch (SvcLogicException e) {
778 logger.error("Error in postVnfdata " + e);
779 throw new RuntimeException(e);
781 if (logger.isTraceEnabled()) {
782 logger.trace("Exiting from postVnfdata with (Result = " + ObjectUtils.toString(false) + ")");
787 private void initMetric() {
788 if (logger.isDebugEnabled())
789 logger.debug("Metric getting initialized");
790 MetricService metricService = getMetricservice();
791 metricRegistry = metricService.createRegistry("APPC");
792 DispatchingFuntionMetric dispatchingFuntionMetric = metricRegistry.metricBuilderFactory().
793 dispatchingFunctionCounterBuilder().
794 withName("DISPATCH_FUNCTION").withType(MetricType.COUNTER).
795 withAcceptRequestValue(0)
796 .withRejectRequestValue(0)
798 if (metricRegistry.register(dispatchingFuntionMetric)) {
799 Metric[] metrics = new Metric[]{dispatchingFuntionMetric};
800 LogPublisher logPublisher = new LogPublisher(metricRegistry, metrics);
801 LogPublisher[] logPublishers = new LogPublisher[1];
802 logPublishers[0] = logPublisher;
803 PublishingPolicy manuallyScheduledPublishingPolicy = metricRegistry.policyBuilderFactory().
804 scheduledPolicyBuilder().withPublishers(logPublishers).
805 withMetrics(metrics).
807 if (logger.isDebugEnabled())
808 logger.debug("Policy getting initialized");
809 manuallyScheduledPublishingPolicy.init();
810 if (logger.isDebugEnabled())
811 logger.debug("Metric initialized");
816 private MetricService getMetricservice() {
817 BundleContext bctx = FrameworkUtil.getBundle(MetricService.class).getBundleContext();
818 ServiceReference sref = bctx.getServiceReference(MetricService.class.getName());
820 logger.info("Metric Service from bundlecontext");
821 return (MetricService) bctx.getService(sref);
823 logger.info("Metric Service error from bundlecontext");
824 logger.warn("Cannot find service reference for org.openecomp.appc.metricservice.MetricService");
830 * This method returns the count of in progress requests
831 * * @return in progress requests count
834 public int getInprogressRequestCount() {
835 if (logger.isTraceEnabled()) {
836 logger.trace("Entering to getInprogressRequestCount");
838 return requestRegistry.getRegisteredRequestCount();