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.oam.processor;
27 import org.openecomp.appc.i18n.Msg;
28 import org.openecomp.appc.oam.AppcOam;
29 import org.openecomp.appc.oam.OAMCommandStatus;
30 import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
32 import java.util.HashMap;
34 import java.util.concurrent.Future;
37 * Base runnable actions for OAM APIs, such as maintenance mode, restart, start and stop API.
39 * <p>This class holds the general action async handling methods for all OAM APIs.
40 * <p>Specific API action runnable will overwrite the general methods to add specific behaviors.
42 * <p>Subclass constructor must set the following class variables:
47 public abstract class BaseActionRunnable extends BaseCommon implements Runnable {
48 final String OAM_OPERATION_TIMEOUT_SECOND = "appc.OAM.api.timeout";
49 /** Default operation tiemout set to 1 minute */
50 final int DEFAULT_OAM_OPERATION_TIMEOUT = 60;
51 /** Abort due to rejection message format with flexible operation name */
52 final String ABORT_MESSAGE_FORMAT = "Aborting %s operation due to %s.";
53 /** Timeout message format with flexible operation name */
54 final String TIMEOUT_MESSAGE_FORMAT = "%s operation has reached timeout %d milliseconds.";
55 /** Failure message format with flexible number of bundles */
56 final String BUNDLE_OPERATION_FAILED_FORMAT = "%d bundle(s) failed, see logs for details.";
57 final String NEW_RPC_OPERATION_REQUEST = "new %s operation request";
58 final String DUE_TO_EXECUTION_ERROR = "due to execution error.";
60 private boolean isWaiting = false;
61 private AppcOamStates currentState;
64 boolean doTimeoutChecking = false;
66 String actionName = "Need to be reset";
68 AppcOamStates finalState;
70 BaseProcessor myParent;
71 Map<String, Future<?>> bundleNameToFuture = new HashMap<>();
76 * @param parent BaseProcessor who has called this constructor.
78 BaseActionRunnable(BaseProcessor parent) {
79 super(parent.logger, parent.configurationHelper, parent.stateHelper, parent.operationHelper);
82 commonHeader = parent.commonHeader;
83 startTime = parent.startTime;
90 * Set timeout in milliseconds
92 void setTimeoutValues() {
93 Integer timeoutSeconds = myParent.timeoutSeconds;
94 if (timeoutSeconds == null) {
95 timeoutMs = configurationHelper.getConfig().getIntegerProperty(
96 OAM_OPERATION_TIMEOUT_SECOND, DEFAULT_OAM_OPERATION_TIMEOUT) * 1000;
98 timeoutMs = timeoutSeconds.longValue() * 1000;
101 doTimeoutChecking = timeoutMs != 0;
102 if (doTimeoutChecking) {
103 startTimeMs = startTime.getTime();
105 logDebug("%s action runnable check timeout (%s) with timeout (%d)ms, and startMs (%d)",
106 rpc.name(), Boolean.toString(doTimeoutChecking), timeoutMs, startTimeMs);
110 * Abort operation handling due to outside interruption, does<br>
111 * - set ABORT status<br>
112 * - send notification message<br>
115 * @param newRpc of the new AppcOam.RPC operation.
117 public void abortRunnable(final AppcOam.RPC newRpc) {
118 resetLogProperties(false);
120 String additionalMsg = String.format(NEW_RPC_OPERATION_REQUEST, newRpc);
121 logDebug("%s action aborted due to %s", rpc.name(), additionalMsg);
122 setStatus(OAMCommandStatus.ABORT, String.format(ABORT_MESSAGE_FORMAT, rpc.name(), additionalMsg));
123 operationHelper.sendNotificationMessage(rpc, commonHeader, status);
124 auditInfoLog(auditMsg);
126 resetLogProperties(true);
132 setInitialLogProperties();
133 logDebug(String.format("===========in %s run (waiting: %s)=======",
134 actionName, Boolean.toString(isWaiting)));
142 isWaiting = !checkState();
147 } catch (Exception e) {
148 logDebug(String.format("%s got exception %s", actionName, e.getMessage()));
149 logger.error(actionName + " exception", e);
152 clearRequestLogProperties();
157 * Keep waiting to be override by children classes for different behaviors.
158 * Timeout is validated here.
161 logDebug(String.format("%s runnable waiting, current state is %s.",
162 actionName, currentState == null ? "null" : currentState.toString()));
164 isTimeout("keepWaiting");
168 * Check if the timeout milliseconds has reached.
170 * @param parentName String of the caller, for logging purpose.
171 * @return true if the timeout has reached, otherwise false.
173 boolean isTimeout(String parentName) {
174 logDebug(String.format("%s task isTimeout called from %s", actionName, parentName));
175 if (doTimeoutChecking
176 && System.currentTimeMillis() - startTimeMs > timeoutMs) {
177 logger.error(String.format("%s operation timeout (%d) ms has reached, abort with error state.",
178 actionName, timeoutMs));
180 setStatus(OAMCommandStatus.TIMEOUT, String.format(TIMEOUT_MESSAGE_FORMAT, rpc.name(), timeoutMs));
181 postAction(AppcOamStates.Error);
188 * Check if all bundle operations are successful through BundleHelper.
189 * If there's failed bundler operation, set error status and trigger postAction with Error state.
191 * @return true if bundler operations have failure, otherwise false.
193 boolean hasBundleOperationFailure() {
194 long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
195 if (failedTask == 0) {
199 setStatus(OAMCommandStatus.UNEXPECTED_ERROR, String.format(BUNDLE_OPERATION_FAILED_FORMAT, failedTask));
200 postAction(AppcOamStates.Error);
205 * Set class <b>status</b> to ABORT with abort message.
207 void setAbortStatus() {
208 setStatus(OAMCommandStatus.ABORT, String.format(ABORT_MESSAGE_FORMAT, rpc.name(), DUE_TO_EXECUTION_ERROR));
212 * Final handling. The thread is cancelled.
214 * @param setState boolean to indicate if set OAM state or not
216 void postDoAction(boolean setState) {
217 logDebug(String.format("Finished %s task", actionName));
221 * Handling for after doAction. does post notification, issue audit log and set OAM state based on input.
223 * @param state of AppcOamState to be set as OAM state when it is not null.
225 void postAction(AppcOamStates state) {
226 operationHelper.sendNotificationMessage(rpc, commonHeader, status);
229 stateHelper.setState(state);
232 auditInfoLog(auditMsg);
234 myParent.cancelAsyncTask();
240 * @return true if final state reached, otherwise return false
242 boolean checkState() {
243 if (isTimeout("checkState")) {
244 myParent.bundleHelper.cancelUnfinished(bundleNameToFuture);
248 if (!myParent.bundleHelper.isAllTaskDone(bundleNameToFuture)) {
252 if (hasBundleOperationFailure()) {
256 currentState = stateHelper.getBundlesState();
257 if (currentState == finalState) {
258 setStatus(OAMCommandStatus.SUCCESS);
265 abstract boolean doAction();