Include impacted changes for APPC-346,APPC-348
[appc.git] / appc-dispatcher / appc-request-handler / appc-request-handler-core / src / main / java / org / onap / appc / requesthandler / impl / RequestHandlerImpl.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
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
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
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.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25 package org.onap.appc.requesthandler.impl;
26
27 import com.att.eelf.configuration.EELFLogger;
28 import com.att.eelf.configuration.EELFManager;
29 import com.att.eelf.i18n.EELFResourceManager;
30 import org.apache.commons.lang.ObjectUtils;
31 import org.onap.appc.domainmodel.lcm.*;
32 import org.onap.appc.exceptions.APPCException;
33 import org.onap.appc.executor.CommandExecutor;
34 import org.onap.appc.executor.objects.CommandExecutorInput;
35 import org.onap.appc.metricservice.metric.DispatchingFuntionMetric;
36 import org.onap.appc.requesthandler.constant.Constants;
37 import org.onap.appc.executor.objects.LCMCommandStatus;
38 import org.onap.appc.executor.objects.Params;
39 import org.onap.appc.i18n.Msg;
40 import org.onap.appc.lockmanager.api.LockException;
41 import org.onap.appc.lockmanager.api.LockManager;
42 import org.onap.appc.logging.LoggingConstants;
43
44 /**
45  * This class provides application logic for the Request/Response Handler Component.
46  */
47 public class RequestHandlerImpl extends AbstractRequestHandlerImpl {
48
49     /**
50      * APP-C VNF lock idle timeout in milliseconds. Applied only when locking VNF using northbound API "lock"
51      */
52     private static final String PROP_IDLE_TIMEOUT = "org.onap.appc.lock.idleTimeout";
53
54     private final EELFLogger logger = EELFManager.getInstance().getLogger(RequestHandlerImpl.class);
55
56     private LockManager lockManager;
57     private CommandExecutor commandExecutor;
58     private boolean isMetricEnabled = false;
59
60     public RequestHandlerImpl() {
61         super();
62     }
63
64     public void setLockManager(LockManager lockManager) {
65         this.lockManager = lockManager;
66     }
67
68     public void setCommandExecutor(CommandExecutor commandExecutor) {
69         this.commandExecutor = commandExecutor;
70     }
71
72     public void handleRequest(RuntimeContext runtimeContext) {
73
74         switch (runtimeContext.getRequestContext().getAction()) {
75             case Lock:
76                 try {
77                     long timeout = configuration.getLongProperty(PROP_IDLE_TIMEOUT, Constants.DEFAULT_IDLE_TIMEOUT);
78                     boolean lockAcquired = lockManager.acquireLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId(), timeout);
79                     logger.info(String.format(lockAcquired ? "Lock acquired for vnfID = %s" : " VnfId  : %s was already locked.", runtimeContext.getVnfContext().getId()));
80                     fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
81                 } catch (LockException e) {
82                     logger.error("Error during Lock operation: " + e.getMessage(), e);
83                     Params params = new Params().addParam("errorMsg", e.getMessage());
84                     fillStatus(runtimeContext, LCMCommandStatus.LOCKED_VNF_ID, params);
85                     storeErrorMessageToLog(runtimeContext,
86                             LoggingConstants.TargetNames.APPC,
87                             LoggingConstants.TargetNames.LOCK_MANAGER,
88                             EELFResourceManager.format(Msg.VF_SERVER_BUSY, runtimeContext.getVnfContext().getId()));
89                 }
90                 break;
91
92             case Unlock:
93                 try {
94                     lockManager.releaseLock(runtimeContext.getVnfContext().getId(), runtimeContext.getRequestContext().getCommonHeader().getRequestId());
95                     logger.info("Lock released for vnfID = " + runtimeContext.getVnfContext().getId());
96                     fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
97                 } catch (LockException e) {
98                     logger.error("Error during Unlock operation: " + e.getMessage(), e);
99                     Params params = new Params().addParam("errorMsg", e.getMessage());
100                     fillStatus(runtimeContext, LCMCommandStatus.LOCKED_VNF_ID, params);
101                 }
102                 break;
103
104             case CheckLock:
105                 boolean isLocked = lockManager.isLocked(runtimeContext.getVnfContext().getId());
106                 fillStatus(runtimeContext, LCMCommandStatus.SUCCESS, null);
107                 runtimeContext.getResponseContext().addKeyValueToAdditionalContext("locked", String.valueOf(isLocked).toUpperCase());
108                 break;
109             default:
110                 callWfOperation(runtimeContext);
111         }
112     }
113
114
115     private void callWfOperation(RuntimeContext runtimeContext) {
116         int remainingTTL = calculateRemainingTTL(runtimeContext.getRequestContext().getCommonHeader());
117         if (remainingTTL > 0) {
118             if (logger.isDebugEnabled()) {
119                 logger.debug("Calling command Executor with remaining TTL value: " + remainingTTL);
120             }
121
122             RuntimeContext clonedContext = cloneContext(runtimeContext);
123
124             CommandExecutorInput commandExecutorInput = new CommandExecutorInput();
125             commandExecutorInput.setRuntimeContext(clonedContext);
126             commandExecutorInput.setTtl(remainingTTL);
127
128             try {
129                 commandExecutor.executeCommand(commandExecutorInput);
130                 if (logger.isTraceEnabled()) {
131                     logger.trace("Command was added to queue successfully for vnfID = " + ObjectUtils.toString(runtimeContext.getRequestContext().getActionIdentifiers().getVnfId()));
132                 }
133                 fillStatus(runtimeContext, LCMCommandStatus.ACCEPTED, null);
134                 if (isMetricEnabled) {
135                     ((DispatchingFuntionMetric) metricRegistry.metric("DISPATCH_FUNCTION")).incrementAcceptedRequest();
136                 }
137             } catch (APPCException e) {
138                 logger.error("Unexpected Error : " + e.getMessage(), e);
139                 String errorMessage = e.getMessage() != null ? e.getMessage() : e.toString();
140                 Params params = new Params().addParam("errorMsg", errorMessage);
141                 fillStatus(runtimeContext, LCMCommandStatus.UNEXPECTED_ERROR, params);
142             }
143
144         } else {
145             fillStatus(runtimeContext, LCMCommandStatus.EXPIRED_REQUEST, null);
146             storeErrorMessageToLog(runtimeContext,
147                     LoggingConstants.TargetNames.APPC,
148                     LoggingConstants.TargetNames.REQUEST_HANDLER,
149                     EELFResourceManager.format(Msg.APPC_EXPIRED_REQUEST,
150                             runtimeContext.getRequestContext().getCommonHeader().getOriginatorId(),
151                             runtimeContext.getRequestContext().getActionIdentifiers().getVnfId(),
152                             String.valueOf(runtimeContext.getRequestContext().getCommonHeader().getFlags().getTtl())));
153         }
154     }
155
156
157     private int calculateRemainingTTL(CommonHeader commonHeader) {
158         if (logger.isTraceEnabled()) {
159             logger.trace("Entering to calculateRemainingTTL with RequestHeader = " + ObjectUtils.toString(commonHeader));
160         }
161         long usedTimeInMillis = (System.currentTimeMillis() - commonHeader.getTimeStamp().getTime());
162         int usedTimeInSeconds = (int) (usedTimeInMillis / 1000);
163         logger.debug("usedTimeInSeconds = " + usedTimeInSeconds + "usedTimeInMillis = " + usedTimeInMillis);
164         // Set ttl value from commonHeader. If not available set it to default
165         Integer inputTTL = (commonHeader.getFlags() == null || commonHeader.getFlags().getTtl() <= 0) ?
166                 Integer.parseInt(configuration.getProperty(Constants.DEFAULT_TTL_KEY, String.valueOf(Constants.DEFAULT_TTL))) :
167                 commonHeader.getFlags().getTtl();
168         logger.debug("inputTTL = " + inputTTL);
169         Integer remainingTTL = inputTTL - usedTimeInSeconds;
170         logger.debug("Remaining TTL = " + remainingTTL);
171         if (logger.isTraceEnabled())
172             logger.trace("Exiting from calculateRemainingTTL with (remainingTTL = " + ObjectUtils.toString(remainingTTL) + ")");
173         return remainingTTL;
174     }
175
176     /*
177     * Workaround to clone context in order to prevent sharing of ResponseContext by two threads (one to set Accepted
178     * status code and other - depending on DG status). Other properties should not be a problem
179     */
180     private RuntimeContext cloneContext(RuntimeContext runtimeContext) {
181         RuntimeContext other = new RuntimeContext();
182         other.setRequestContext(runtimeContext.getRequestContext());
183         other.setResponseContext(new ResponseContext());
184         other.getResponseContext().setStatus(new Status());
185         other.getResponseContext().setCommonHeader(runtimeContext.getRequestContext().getCommonHeader());
186         other.setVnfContext(runtimeContext.getVnfContext());
187         other.setRpcName(runtimeContext.getRpcName());
188         other.setTimeStart(runtimeContext.getTimeStart());
189         other.setTransactionRecord(runtimeContext.getTransactionRecord());
190         return other;
191     }
192
193
194     /**
195      * 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.
196      *
197      * @param vnfId                   String of VNF ID
198      * @param readOnlyActivity        boolean indicator
199      * @param forceFlag               boolean indicator
200      */
201     @Override
202     public void onRequestExecutionStart(String vnfId, boolean readOnlyActivity, boolean forceFlag) {
203
204     }
205 }