Code cleanup to resolve critical sonar issues
[policy/drools-applications.git] / controlloop / common / eventmanager / src / main / java / org / onap / policy / controlloop / eventmanager / ControlLoopOperationManager.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * controlloop operation manager
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop.eventmanager;
22
23 import java.io.Serializable;
24 import java.sql.Timestamp;
25 import java.time.Instant;
26 import java.util.LinkedList;
27
28 import javax.persistence.EntityManager;
29 import javax.persistence.Persistence;
30
31 import org.onap.policy.appc.Response;
32 import org.onap.policy.appc.ResponseCode;
33 import org.onap.policy.controlloop.ControlLoopEvent;
34 import org.onap.policy.controlloop.ControlLoopOperation;
35 import org.onap.policy.controlloop.VirtualControlLoopEvent;
36 import org.onap.policy.controlloop.ControlLoopException;
37 import org.onap.policy.controlloop.policy.Policy;
38 import org.onap.policy.controlloop.policy.PolicyResult;
39 import org.onap.policy.controlloop.actor.appc.APPCActorServiceProvider;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43
44 public class ControlLoopOperationManager implements Serializable {
45         
46         /**
47          * 
48          */
49         private static final long serialVersionUID = -3773199283624595410L;
50         private static final Logger logger = LoggerFactory.getLogger(ControlLoopOperationManager.class);
51
52         @Override
53         public String toString() {
54                 return "ControlLoopOperationManager [onset=" + (onset != null ? onset.requestID : "null") + ", policy=" 
55                                 + (policy != null ? policy.getId() : "null") + ", attempts=" + attempts
56                                 + ", policyResult=" + policyResult 
57                                 + ", currentOperation=" + currentOperation + ", operationHistory=" + operationHistory
58                                 + "]";
59         }
60
61         //
62         // These properties are not changeable, but accessible
63         // for Drools Rule statements.
64         //
65         //public final ATTControlLoopEvent onset;
66         public final ControlLoopEvent onset;
67         public final Policy policy;
68
69         //
70         // Properties used to track the Operation
71         //
72         private int attempts = 0;
73         private Operation currentOperation = null;
74         private LinkedList<Operation> operationHistory = new LinkedList<Operation>();
75         private PolicyResult policyResult = null;
76         private ControlLoopEventManager eventManager = null;
77
78         public ControlLoopEventManager getEventManager() {
79                 return eventManager;
80         }
81
82         public void setEventManager(ControlLoopEventManager eventManager) {
83                 this.eventManager = eventManager;
84         }
85
86
87         //
88         // Internal class used for tracking
89         //
90         private class Operation {
91                 public ControlLoopOperation operation = new ControlLoopOperation();
92                 public PolicyResult policyResult = null;
93                 public int attempt = 0;
94                 
95                 @Override
96                 public String toString() {
97                         return "Operation [attempt=" + attempt + ", policyResult=" + policyResult + ", operation=" + operation
98                                         + "]";
99                 }
100         }
101         
102         private String guardApprovalStatus = "NONE";//"NONE", "PERMIT", "DENY"
103         private Object operationRequest;
104         
105         public Object getOperationRequest() {
106                 return operationRequest;
107         }
108
109         public String getGuardApprovalStatus() {
110                 return guardApprovalStatus;
111         }
112         public void setGuardApprovalStatus(String guardApprovalStatus) {
113                 this.guardApprovalStatus = guardApprovalStatus;
114         }
115         
116         
117         public ControlLoopOperationManager(/*ATTControlLoopEvent*/ControlLoopEvent onset, Policy policy, ControlLoopEventManager em) throws ControlLoopException {
118                 this.onset = onset;
119                 this.policy = policy;
120                 this.guardApprovalStatus = "NONE";
121                 this.eventManager = em;
122                 
123                 //
124                 // Let's make a sanity check
125                 //
126                 switch (policy.getActor()) {
127                 case "APPC":
128                         break;
129                 case "AOTS":
130                         break;
131                 case "MSO":
132                         break;
133                 case "SDNO":
134                         break;
135                 case "SDNR":
136                         break;
137                 default:
138                         throw new ControlLoopException("ControlLoopEventManager: policy has an unknown actor.");
139                 }
140         }
141         
142         public Object startOperation(/*VirtualControlLoopEvent*/ControlLoopEvent onset) {
143                 //
144                 // They shouldn't call us if we currently running something
145                 //
146                 if (this.currentOperation != null) {
147                         //
148                         // what do we do if we are already running an operation?
149                         //
150                         return null;
151                 }
152                 //
153                 // Check if we have maxed out on retries
154                 //
155                 if (this.policy.getRetry() == null || this.policy.getRetry() < 1) {
156                         //
157                         // No retries are allowed, so check have we even made
158                         // one attempt to execute the operation?
159                         //
160                         if (this.attempts >= 1) {
161                                 //
162                                 // We have, let's ensure our PolicyResult is set
163                                 //
164                                 if (this.policyResult == null) {
165                                         this.policyResult = PolicyResult.FAILURE_RETRIES;
166                                 }
167                                 //
168                                 //
169                                 //
170                                 return null;
171                         }
172                 } else {
173                         //
174                         // Have we maxed out on retries?
175                         //
176                         if (this.attempts > this.policy.getRetry()) {
177                                 if (this.policyResult == null) {
178                                         this.policyResult = PolicyResult.FAILURE_RETRIES;
179                                 }
180                                 return null;
181                         }
182                 }
183                 //
184                 // Setup
185                 //
186                 this.policyResult = null;
187                 Operation operation = new Operation();
188                 operation.attempt = ++this.attempts;
189                 operation.operation.actor = this.policy.getActor().toString();
190                 operation.operation.operation = this.policy.getRecipe();
191                 operation.operation.target = this.policy.getTarget().toString();
192                 operation.operation.subRequestId = Integer.toString(operation.attempt);
193                 //
194                 // Now determine which actor we need to construct a request for
195                 //
196                 switch (policy.getActor()) {
197                 case "APPC":
198                         //Request request = APPCActorServiceProvider.constructRequest(onset, operation.operation, this.policy);
199                         this.operationRequest = APPCActorServiceProvider.constructRequest((VirtualControlLoopEvent)onset, operation.operation, this.policy);
200                         //
201                         // Save the operation
202                         //
203                         this.currentOperation = operation;
204                         //System.out.print("*************   BEFORE STORING.....");
205                         //this.storeOperationInDataBase("startOperation");
206                         //System.out.print("*************   AFTER STORING.....");
207                         //
208                         return operationRequest;
209                 case "MSO":
210                         //
211                         // We are not supporting MSO interface at the moment
212                         //
213                         System.out.println("We are not supporting MSO actor in the latest release.");
214                         return null;
215                 }
216                 return null;
217         }
218         
219         public PolicyResult     onResponse(Object response) {
220                 //
221                 // Which response is it?
222                 //
223                 if (response instanceof Response) {
224                         //
225                         // Cast it
226                         //
227                         Response appcResponse = (Response) response;
228                         //
229                         // Determine which subrequestID (ie. attempt)
230                         //
231                         Integer operationAttempt = null;
232                         try {
233                                 operationAttempt = Integer.parseInt(appcResponse.CommonHeader.SubRequestID);
234                         } catch (NumberFormatException e) {
235                                 //
236                                 // We cannot tell what happened if this doesn't exist
237                                 //
238                                 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C SubRequestID (it was null).", PolicyResult.FAILURE_EXCEPTION);
239                                 return PolicyResult.FAILURE_EXCEPTION;
240                         }
241                         //
242                         // Sanity check the response message
243                         //
244                         if (appcResponse.Status == null) {
245                                 //
246                                 // We cannot tell what happened if this doesn't exist
247                                 //
248                                 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C response status field (it was null).", PolicyResult.FAILURE_EXCEPTION);
249                                 return PolicyResult.FAILURE_EXCEPTION;
250                         }
251                         //
252                         // Get the Response Code
253                         //
254                         ResponseCode code = ResponseCode.toResponseCode(appcResponse.Status.Code);
255                         if (code == null) {
256                                 //
257                                 // We are unaware of this code
258                                 //
259                                 this.completeOperation(operationAttempt, "Policy was unable to parse APP-C response status code field.", PolicyResult.FAILURE_EXCEPTION);
260                                 return PolicyResult.FAILURE_EXCEPTION;
261                         }
262                         //
263                         // Ok, let's figure out what APP-C's response is
264                         //
265                         switch (code) {
266                         case ACCEPT:
267                                 //
268                                 // This is good, they got our original message and
269                                 // acknowledged it.
270                                 //
271                                 // Is there any need to track this?
272                                 //
273                                 return null;
274                         case ERROR:
275                         case REJECT:
276                                 //
277                                 // We'll consider these two codes as exceptions
278                                 //
279                                 this.completeOperation(operationAttempt, appcResponse.getStatus().Description, PolicyResult.FAILURE_EXCEPTION);
280                                 if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
281                                         return null;
282                                 }
283                                 return PolicyResult.FAILURE_EXCEPTION;
284                         case SUCCESS:
285                                 //
286                                 //
287                                 //
288                                 this.completeOperation(operationAttempt, appcResponse.getStatus().Description, PolicyResult.SUCCESS);
289                                 if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
290                                         return null;
291                                 }
292                                 return PolicyResult.SUCCESS;
293                         case FAILURE:
294                                 //
295                                 //
296                                 //
297                                 this.completeOperation(operationAttempt, appcResponse.getStatus().Description, PolicyResult.FAILURE);
298                                 if (this.policyResult != null && this.policyResult.equals(PolicyResult.FAILURE_TIMEOUT)) {
299                                         return null;
300                                 }
301                                 return PolicyResult.FAILURE;
302                         }
303                 } 
304                 return null;
305         }
306         
307         public Integer  getOperationTimeout() {
308                 //
309                 // Sanity check
310                 //
311                 if (this.policy == null) {
312                         System.out.println("getOperationTimeout returning 0");
313                         return 0;
314                 }
315                 System.out.println("getOperationTimeout returning " + this.policy.getTimeout());
316                 return this.policy.getTimeout();
317         }
318         
319         public String   getOperationTimeoutString(int defaultTimeout) {
320                 Integer to = this.getOperationTimeout();
321                 if (to == null || to == 0) {
322                         return Integer.toString(defaultTimeout) + "s";
323                 }
324                 return to.toString() + "s";
325         }
326         
327         public PolicyResult     getOperationResult() {
328                 return this.policyResult;
329         }
330         
331         public String   getOperationMessage() {
332                 if (this.currentOperation != null && this.currentOperation.operation != null) {
333                         return this.currentOperation.operation.toMessage();
334                 }
335                 if (this.operationHistory != null && this.operationHistory.size() > 0) {
336                         return this.operationHistory.getLast().operation.toMessage();
337                 }
338                 return null;
339         }
340         
341         public String   getOperationMessage(String guardResult) {
342                 if (this.currentOperation != null && this.currentOperation.operation != null) {
343                         return this.currentOperation.operation.toMessage()+ ", Guard result: " + guardResult;
344                 }
345                 if (this.operationHistory != null && this.operationHistory.size() > 0) {
346                         return this.operationHistory.getLast().operation.toMessage() + ", Guard result: " + guardResult;
347                 }
348                 return null;
349         }
350         
351         public String   getOperationHistory() {
352                 if (this.currentOperation != null && this.currentOperation.operation != null) {
353                         return this.currentOperation.operation.toHistory();
354                 }
355                 if (this.operationHistory != null && this.operationHistory.size() > 0) {
356                         return this.operationHistory.getLast().operation.toHistory();
357                 }
358                 return null;
359         }
360         
361         public LinkedList<ControlLoopOperation> getHistory() {
362                 LinkedList<ControlLoopOperation> history = new LinkedList<ControlLoopOperation>();
363                 for (Operation op : this.operationHistory) {
364                         history.add(new ControlLoopOperation(op.operation));
365                         
366                 }
367                 return history;
368         }
369         
370         public void             setOperationHasTimedOut() {
371                 //
372                 //
373                 //
374                 this.completeOperation(this.attempts, "Operation timed out", PolicyResult.FAILURE_TIMEOUT);
375         }
376         
377         public void             setOperationHasGuardDeny() {
378                 //
379                 //
380                 //
381                 this.completeOperation(this.attempts, "Operation denied by Guard", PolicyResult.FAILURE_GUARD);
382         }
383
384         public boolean  isOperationComplete() {
385                 //
386                 // Is there currently a result?
387                 //
388                 if (this.policyResult == null) {
389                         //
390                         // either we are in process or we
391                         // haven't started
392                         //
393                         return false;
394                 }
395                 //
396                 // We have some result, check if the operation failed
397                 //
398                 if (this.policyResult.equals(PolicyResult.FAILURE)) {
399                         //
400                         // Check if there were no retries specified
401                         //
402                         if (policy.getRetry() == null || policy.getRetry() == 0) {
403                                 //
404                                 // The result is the failure
405                                 //
406                                 return true;
407                         }
408                         //
409                         // Check retries
410                         //
411                         if (this.isRetriesMaxedOut()) {
412                                 //
413                                 // No more attempts allowed, reset
414                                 // that our actual result is failure due to retries
415                                 //
416                                 this.policyResult = PolicyResult.FAILURE_RETRIES;
417                                 return true;
418                         } else {
419                                 //
420                                 // There are more attempts available to try the
421                                 // policy recipe.
422                                 //
423                                 return false;
424                         }
425                 }
426                 //
427                 // Other results mean we are done
428                 //
429                 return true;
430         }
431         
432         public boolean  isOperationRunning() {
433                 return (this.currentOperation != null);
434         }
435         
436         private boolean isRetriesMaxedOut() {
437                 if (policy.getRetry() == null || policy.getRetry() == 0) {
438                         //
439                         // There were NO retries specified, so declare
440                         // this as completed.
441                         //
442                         return (this.attempts > 0);
443                 }
444                 return (this.attempts > policy.getRetry());
445         }
446         
447         private void    storeOperationInDataBase(){
448                 
449                 EntityManager em;
450                 try{
451                         em = Persistence.createEntityManagerFactory("OperationsHistoryPU").createEntityManager();//emf.createEntityManager();           
452                 }catch(Exception e){
453                         logger.error("storeOperationInDataBase threw: ", e);
454                         return; 
455                 }
456                         
457                 OperationsHistoryDbEntry newEntry = new OperationsHistoryDbEntry(); 
458                         
459                 newEntry.closedLoopName = this.onset.closedLoopControlName;
460                 newEntry.requestId = this.onset.requestID.toString();
461                 newEntry.actor = this.currentOperation.operation.actor;
462                 newEntry.operation = this.currentOperation.operation.operation;
463                 newEntry.target = this.eventManager.getTargetInstance(this.policy);
464                 newEntry.starttime = Timestamp.from(this.currentOperation.operation.start);
465                 newEntry.subrequestId = this.currentOperation.operation.subRequestId;
466                 newEntry.endtime = new Timestamp(this.currentOperation.operation.end.toEpochMilli());
467                 newEntry.message = this.currentOperation.operation.message;
468                 newEntry.outcome = this.currentOperation.operation.outcome;
469                         
470                 em.getTransaction().begin();
471                 em.persist(newEntry);
472                 em.getTransaction().commit();
473                         
474                 em.close();
475
476         }
477
478         
479         
480         private void    completeOperation(Integer attempt, String message, PolicyResult result) {
481                 if (attempt == null) {
482                         System.out.println("attempt cannot be null (i.e. subRequestID)");
483                         return;
484                 }
485                 if (this.currentOperation != null) {
486                         if (this.currentOperation.attempt == attempt.intValue()) {
487                                 this.currentOperation.operation.end = Instant.now();
488                                 this.currentOperation.operation.message = message;
489                                 this.currentOperation.operation.outcome = result.toString();
490                                 this.currentOperation.policyResult = result;
491                                 //
492                                 // Save it in history
493                                 //
494                                 this.operationHistory.add(this.currentOperation);
495                                 this.storeOperationInDataBase();
496                                 //
497                                 // Set our last result
498                                 //
499                                 this.policyResult = result;
500                                 //
501                                 // Clear the current operation field
502                                 //
503                                 this.currentOperation = null;
504                                 return;
505                         }
506                         System.out.println("not current");
507                 }
508                 for (Operation op : this.operationHistory) {
509                         if (op.attempt == attempt.intValue()) {
510                                 op.operation.end = Instant.now();
511                                 op.operation.message = message;
512                                 op.operation.outcome = result.toString();
513                                 op.policyResult = result;
514                                 return;
515                         }
516                 }
517                 System.out.println("Could not find associated operation");
518                 
519         }
520         
521 }