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 /** Abort due to rejection message format with flexible operation name */
49 final String ABORT_MESSAGE_FORMAT = "Aborting %s operation due to %s.";
50 /** Timeout message format with flexible operation name */
51 final String TIMEOUT_MESSAGE_FORMAT = "%s operation has reached timeout %d milliseconds.";
52 /** Failure message format with flexible number of bundles */
53 final String BUNDLE_OPERATION_FAILED_FORMAT = "%d bundle(s) failed, see logs for details.";
54 final String NEW_RPC_OPERATION_REQUEST = "new %s operation request";
55 final String DUE_TO_EXECUTION_ERROR = "due to execution error.";
57 private boolean isWaiting = false;
60 boolean doTimeoutChecking = false;
62 String actionName = "Need to be reset";
64 AppcOamStates finalState;
66 BaseProcessor myParent;
67 Map<String, Future<?>> bundleNameToFuture = new HashMap<>();
72 * @param parent BaseProcessor who has called this constructor.
74 BaseActionRunnable(BaseProcessor parent) {
75 super(parent.logger, parent.configurationHelper, parent.stateHelper, parent.operationHelper);
78 commonHeader = parent.commonHeader;
84 * Collect the timeout value for this {@link BaseActionRunnable}
86 void setTimeoutValues() {
87 startTime = myParent.startTime;
88 timeoutMs = myParent.getTimeoutMilliseconds();
89 doTimeoutChecking = timeoutMs != 0;
90 if (doTimeoutChecking) {
91 startTimeMs = startTime.getTime();
93 logDebug("%s action runnable check timeout (%s) with timeout (%d)ms, and startMs (%d)",
94 rpc.name(), Boolean.toString(doTimeoutChecking), timeoutMs, startTimeMs);
99 * Abort operation handling due to outside interruption, does<br>
100 * - set ABORT status<br>
101 * - send notification message<br>
104 * @param newRpc of the new AppcOam.RPC operation.
106 void abortRunnable(final AppcOam.RPC newRpc) {
107 resetLogProperties(false);
109 String additionalMsg = String.format(NEW_RPC_OPERATION_REQUEST, newRpc);
110 logDebug("%s action aborted due to %s", rpc.name(), additionalMsg);
111 setStatus(OAMCommandStatus.ABORT, String.format(ABORT_MESSAGE_FORMAT, rpc.name(), additionalMsg));
112 operationHelper.sendNotificationMessage(rpc, commonHeader, status);
113 auditInfoLog(auditMsg);
115 resetLogProperties(true);
121 setInitialLogProperties();
122 logDebug(String.format("===========in %s run (waiting: %s)=======",
123 actionName, Boolean.toString(isWaiting)));
131 isWaiting = !checkState();
136 } catch (Exception e) {
137 logDebug(String.format("%s got exception %s", actionName, e.getMessage()));
138 logger.error(actionName + " exception", e);
141 clearRequestLogProperties();
146 * Keep waiting to be override by children classes for different behaviors.
147 * Timeout is validated here.
150 logDebug(String.format("%s runnable waiting, current state is %s.",
151 actionName, stateHelper.getCurrentOamState()));
153 isTimeout("keepWaiting");
157 * Check if the timeout milliseconds has reached.
159 * @param parentName String of the caller, for logging purpose.
160 * @return true if the timeout has reached, otherwise false.
162 boolean isTimeout(String parentName) {
163 logDebug(String.format("%s task isTimeout called from %s", actionName, parentName));
164 if (doTimeoutChecking
165 && System.currentTimeMillis() - startTimeMs > timeoutMs) {
166 logger.error(String.format("%s operation timeout (%d) ms has reached, abort with error state.",
167 actionName, timeoutMs));
169 setStatus(OAMCommandStatus.TIMEOUT, String.format(TIMEOUT_MESSAGE_FORMAT, rpc.name(), timeoutMs));
170 postAction(AppcOamStates.Error);
177 * Check if all bundle operations are successful through BundleHelper.
178 * If there's failed bundler operation, set error status and trigger postAction with Error state.
180 * @return true if bundler operations have failure, otherwise false.
182 boolean hasBundleOperationFailure() {
183 long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
184 if (failedTask == 0) {
188 setStatus(OAMCommandStatus.UNEXPECTED_ERROR, String.format(BUNDLE_OPERATION_FAILED_FORMAT, failedTask));
189 postAction(AppcOamStates.Error);
194 * Set class <b>status</b> to ABORT with abort message.
196 void setAbortStatus() {
197 setStatus(OAMCommandStatus.ABORT, String.format(ABORT_MESSAGE_FORMAT, rpc.name(), DUE_TO_EXECUTION_ERROR));
201 * Final handling. The thread is cancelled.
203 * @param setState boolean to indicate if set OAM state or not
205 void postDoAction(boolean setState) {
206 logDebug(String.format("Finished %s task", actionName));
210 * Handling for after doAction. does post notification, issue audit log and set OAM state based on input.
212 * @param state of AppcOamState to be set as OAM state when it is not null.
214 void postAction(AppcOamStates state) {
215 operationHelper.sendNotificationMessage(rpc, commonHeader, status);
218 stateHelper.setState(state);
221 auditInfoLog(auditMsg);
223 myParent.cancelAsyncTask();
229 * @return true if final state reached, otherwise return false
231 boolean checkState() {
232 if (isTimeout("checkState")) {
233 myParent.bundleHelper.cancelUnfinished(bundleNameToFuture);
237 if (!myParent.bundleHelper.isAllTaskDone(bundleNameToFuture)) {
241 if (hasBundleOperationFailure()) {
245 if (stateHelper.getBundlesState() == finalState) {
246 setStatus(OAMCommandStatus.SUCCESS);
253 abstract boolean doAction();