OAM operations 2 - oam
[appc.git] / appc-oam / appc-oam-bundle / src / main / java / org / openecomp / appc / oam / processor / BaseActionRunnable.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.openecomp.appc.oam.processor;
26
27 import org.openecomp.appc.i18n.Msg;
28 import org.openecomp.appc.oam.OAMCommandStatus;
29 import org.openecomp.appc.statemachine.impl.readers.AppcOamStates;
30
31 import java.util.HashMap;
32 import java.util.Map;
33 import java.util.concurrent.Future;
34
35 /**
36  * Base runnable actions for OAM APIs, such as maintenance mode, restart, start and stop API.
37  *
38  * <p>This class holds the general action async handling methods for all OAM APIs.
39  * <p>Specific API action runnable will overwrite the general methods to add specific behaviors.
40  *
41  * <p>Subclass constructor must set the following class variables:
42  *   <br>  - actionName
43  *   <br>  - auditMsg
44  *   <br>  - finalState
45  */
46 abstract class BaseActionRunnable extends BaseCommon implements Runnable {
47     final String OAM_OPERATION_TIMEOUT_SECOND = "appc.OAM.api.timeout";
48     /** Default operation tiemout set to 1 minute */
49     final int DEFAULT_OAM_OPERATION_TIMEOUT = 60;
50     /** Abort message format with flexible operation name */
51     final String ABORT_MESSAGE_FORMAT = "Aborting %s operation.";
52     /** Timeout message format with flexible operation name */
53     final String TIMEOUT_MESSAGE_FORMAT = "%s operation has reached timeout %d milliseconds.";
54
55     private boolean isWaiting = false;
56     private AppcOamStates currentState;
57     long startTimeMs = 0;
58     long timeoutMs = 0;
59     boolean doTimeoutChecking = false;
60
61     String actionName = "Need to be reset";
62     Msg auditMsg;
63     AppcOamStates finalState;
64
65     BaseProcessor myParent;
66     Map<String, Future<?>> bundleNameToFuture = new HashMap<>();
67
68     BaseActionRunnable(BaseProcessor parent) {
69         super(parent.logger, parent.configurationHelper, parent.stateHelper, parent.operationHelper);
70
71         rpc = parent.rpc;
72         commonHeader = parent.commonHeader;
73         startTime = parent.startTime;
74         myParent = parent;
75
76         setTimeoutValues();
77     }
78
79     void setTimeoutValues() {
80         Integer timeoutSeconds = myParent.timeoutSeconds;
81         if (timeoutSeconds == null) {
82             timeoutMs = configurationHelper.getConfig().getIntegerProperty(
83                     OAM_OPERATION_TIMEOUT_SECOND, DEFAULT_OAM_OPERATION_TIMEOUT) * 1000;
84         } else {
85             timeoutMs = timeoutSeconds.longValue() * 1000;
86         }
87
88         doTimeoutChecking = timeoutMs != 0;
89         if (doTimeoutChecking) {
90             startTimeMs = startTime.getTime();
91         }
92         logDebug("%s action runnable check timeout (%s) with timeout (%d)ms, and startMs (%d)",
93                 rpc.name(), Boolean.toString(doTimeoutChecking), timeoutMs, startTimeMs);
94     }
95
96     @Override
97     public void run() {
98         try {
99             setInitialLogProperties();
100             logDebug(String.format("===========in %s run (waiting: %s)=======",
101                     actionName, Boolean.toString(isWaiting)));
102
103             if (isWaiting) {
104                 if (!checkState()) {
105                     keepWaiting();
106                 }
107             } else {
108                 if (doAction()) {
109                     isWaiting = !checkState();
110                 } else {
111                     postDoAction(false);
112                 }
113             }
114         } catch (Exception e) {
115             logDebug(String.format("%s got exception %s", actionName, e.getMessage()));
116             logger.error(actionName + " exception", e);
117
118         } finally {
119             clearRequestLogProperties();
120         }
121     }
122
123     void keepWaiting() {
124         logDebug(String.format("%s runnable waiting, current state is %s.",
125                 actionName, currentState == null ? "null" : currentState.toString()));
126
127         isTimeout("keepWaiting");
128     }
129
130     boolean isTimeout(String parentName) {
131         logDebug(String.format("%s task isTimeout called from %s", actionName, parentName));
132         if (doTimeoutChecking
133                 && System.currentTimeMillis() - startTimeMs > timeoutMs) {
134             logger.error(String.format("%s operation timeout (%d) ms has reached, abort with error state.",
135                     actionName, timeoutMs));
136
137             setStatus(OAMCommandStatus.TIMEOUT, String.format(TIMEOUT_MESSAGE_FORMAT, rpc.name(), timeoutMs));
138             postAction(AppcOamStates.Error);
139             return true;
140         }
141         return false;
142     }
143
144     /**
145      * Set class <b>status</b> to REJECTED with abort message.
146      */
147     void setAbortStatus() {
148         setStatus(OAMCommandStatus.REJECTED, String.format(ABORT_MESSAGE_FORMAT, rpc.name()));
149     }
150
151     /**
152      * Final handling. The thread is cancelled.
153      * @param setState boolean to indicate if set OAM state or not
154      */
155     void postDoAction(boolean setState) {
156         logDebug(String.format("Finished %s task", actionName));
157     }
158
159     /**
160      * Handling for after doAction. does post notification,  issue audit log and set OAM state based on input
161      * @param state of AppcOamState to be set as OAM state when it is not null.
162      */
163     void postAction(AppcOamStates state) {
164         operationHelper.sendNotificationMessage(rpc, commonHeader, status);
165
166         if (state != null) {
167             stateHelper.setState(state);
168         }
169
170         auditInfoLog(auditMsg);
171
172         myParent.cancelAsyncTask();
173     }
174
175     /**
176      * Check state
177      * @return true if final state reached, otherwise return false
178      */
179     boolean checkState() {
180         if (isTimeout("checkState")) {
181             myParent.bundleHelper.cancelUnfinished(bundleNameToFuture);
182             return true;
183         }
184
185         if (!myParent.bundleHelper.isAllTaskDone(bundleNameToFuture)) {
186             return false;
187         }
188
189         long failedTask = myParent.bundleHelper.getFailedMetrics(bundleNameToFuture);
190         if (failedTask != 0) {
191             String errorMsg = failedTask + " bundle(s) failed, see logs for details.";
192             setStatus(OAMCommandStatus.UNEXPECTED_ERROR, errorMsg);
193             postAction(AppcOamStates.Error);
194             return true;
195         }
196
197         currentState = stateHelper.getBundlesState();
198         if (currentState == finalState) {
199             setStatus(OAMCommandStatus.SUCCESS);
200             postDoAction(true);
201             return true;
202         }
203         return false;
204     }
205
206     abstract boolean doAction();
207 }