d8e34313eb6c37af2f8ad14fdaa04e8ac1c00e39
[policy/drools-applications.git] / controlloop / templates / archetype-cl-casablanca / src / main / resources / archetype-resources / src / main / resources / __closedLoopControlName__.drl
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2018-2019 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;
22
23 import org.onap.policy.controlloop.params.ControlLoopParams;
24 import org.onap.policy.controlloop.VirtualControlLoopEvent;
25 import org.onap.policy.controlloop.VirtualControlLoopNotification;
26 import org.onap.policy.controlloop.ControlLoopEventStatus;
27 import org.onap.policy.controlloop.ControlLoopNotificationType;
28 import org.onap.policy.controlloop.ControlLoopLogger;
29 import org.onap.policy.controlloop.policy.PolicyResult;
30 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
31 import org.onap.policy.controlloop.policy.Policy;
32 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
33 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS;
34 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
35 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
36 import org.onap.policy.aai.AaiNqResponseWrapper;
37 import org.onap.policy.appc.Request;
38 import org.onap.policy.appc.Response;
39 import org.onap.policy.appc.CommonHeader;
40 import org.onap.policy.appclcm.LcmRequestWrapper;
41 import org.onap.policy.appclcm.LcmResponseWrapper;
42 import org.onap.policy.appclcm.LcmRequest;
43 import org.onap.policy.appclcm.LcmResponse;
44 import org.onap.policy.appclcm.LcmCommonHeader;
45 import org.onap.policy.sdnr.PciRequestWrapper;
46 import org.onap.policy.sdnr.PciResponseWrapper;
47 import org.onap.policy.sdnr.PciRequest;
48 import org.onap.policy.sdnr.PciResponse;
49 import org.onap.policy.vfc.VfcRequest;
50 import org.onap.policy.vfc.VfcResponse;
51 import org.onap.policy.vfc.VfcManager;
52 import org.onap.policy.so.SOManager;
53 import org.onap.policy.so.SORequest;
54 import org.onap.policy.so.SORequestStatus;
55 import org.onap.policy.so.SORequestDetails;
56 import org.onap.policy.so.SOModelInfo;
57 import org.onap.policy.so.SOCloudConfiguration;
58 import org.onap.policy.so.SORequestInfo;
59 import org.onap.policy.so.SORequestParameters;
60 import org.onap.policy.so.SORelatedInstanceListElement;
61 import org.onap.policy.so.SORelatedInstance;
62 import org.onap.policy.so.SOResponse;
63 import org.onap.policy.so.SOResponseWrapper;
64 import org.onap.policy.sdnc.SdncRequest;
65 import org.onap.policy.sdnc.SdncManager;
66 import org.onap.policy.sdnc.SdncResponse;
67 import org.onap.policy.guard.PolicyGuard;
68 import org.onap.policy.guard.PolicyGuard.LockResult;
69 import org.onap.policy.guard.TargetLock;
70 import org.onap.policy.guard.GuardResult;
71 import org.onap.policy.guard.PolicyGuardRequest;
72 import org.onap.policy.guard.PolicyGuardResponse;
73 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
74 import org.onap.policy.guard.PolicyGuardXacmlHelper;
75
76 import org.yaml.snakeyaml.Yaml;
77 import org.yaml.snakeyaml.constructor.Constructor;
78
79 import org.slf4j.LoggerFactory;
80 import org.slf4j.Logger;
81
82 import java.time.Instant;
83 import java.util.LinkedList;
84 import java.util.Iterator;
85
86 import org.onap.policy.drools.system.PolicyEngine;
87
88 /*
89  * This object is to provide support for timeouts
90  * due to a bug in drools' built-in timers
91  */
92 declare ControlLoopTimer
93     closedLoopControlName : String
94     requestID : String
95     delay : String
96     expired : boolean
97     //timerType is the type of timer: either "ClosedLoop" or "Operation"
98     timerType : String
99 end
100
101 /*
102 *
103 * Called when the ControlLoopParams object has been inserted into working memory from the BRMSGW.
104 *
105 */
106 rule "INSERT.PARAMS"
107     when
108         $params : ControlLoopParams()
109     then
110
111     // Note: globals have bad behavior when persistence is used,
112     //       hence explicitly getting the logger vs using a global
113
114     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
115     logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "." 
116         + drools.getRule().getName(), $params.getControlLoopYaml());
117 end
118
119 /*
120 *
121 * This rule responds to DCAE Events where there is no manager yet. Either it is
122 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
123 *
124 */
125 rule "EVENT"
126     when
127         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
128         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
129         not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
130             requestID == $event.getRequestId() ) )
131     then
132
133     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
134     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
135
136     try {
137
138         //
139         // Check the event, because we need it to not be null when
140         // we create the ControlLoopEventManager. The ControlLoopEventManager
141         // will do extra syntax checking as well check if the closed loop is disabled.
142         //
143         if ($event.getRequestId() == null) {
144             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
145             notification.setNotification(ControlLoopNotificationType.REJECTED);
146             notification.setFrom("policy");
147             notification.setMessage("Missing requestID");
148             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
149             notification.setPolicyScope($params.getPolicyScope());
150             notification.setPolicyVersion($params.getPolicyVersion());
151
152             //
153             // Let interested parties know
154             //
155             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
156
157             //
158             // Retract it from memory
159             //
160             retract($event);
161         } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
162             throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
163         } else {
164             //
165             // Create an EventManager
166             //
167             ControlLoopEventManager manager = new ControlLoopEventManager($clName, $event.getRequestId());
168             //
169             // Determine if EventManager can actively process the event 
170             // (i.e. syntax, is_closed_loop_disabled checks etc.)
171             //
172             VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
173             notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
174             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
175             notification.setPolicyScope($params.getPolicyScope());
176             notification.setPolicyVersion($params.getPolicyVersion());
177             //
178             // Are we actively pursuing this event?
179             //
180             if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
181                 //
182                 // Insert Event Manager into memory, this will now kick off processing.
183                 //
184                 insert(manager);
185                 //
186                 // Let interested parties know
187                 //
188                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
189                 //
190                 // Setup the Overall Control Loop timer
191                 //
192                 ControlLoopTimer clTimer = new ControlLoopTimer();
193                 clTimer.setTimerType("ClosedLoop");
194                 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
195                 clTimer.setRequestID($event.getRequestId().toString());
196                 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
197                 //
198                 // Insert it
199                 //
200                 insert(clTimer);
201             } else {
202                 //
203                 // Let interested parties know
204                 //
205                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
206                 //
207                 // Retract it from memory
208                 //
209                 retract($event);
210             }
211
212             //
213             // Now that the manager is inserted into Drools working memory, we'll wait for
214             // another rule to fire in order to continue processing. This way we can also
215             // then screen for additional ONSET and ABATED events for this RequestID.
216             //
217         }
218     } catch (Exception e) {
219         logger.warn("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName(), e);
220
221         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
222         notification.setNotification(ControlLoopNotificationType.REJECTED);
223         notification.setMessage("Exception occurred: " + e.getMessage());
224         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
225         notification.setPolicyScope($params.getPolicyScope());
226         notification.setPolicyVersion($params.getPolicyVersion());
227         //
228         //
229         //
230         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
231         //
232         // Retract the event
233         //
234         retract($event);
235     }
236 end
237
238 /*
239 *
240 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
241 * is now created. We can start processing the yaml specification via the Event Manager.
242 *
243 */
244 rule "EVENT.MANAGER"
245     when
246         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
247         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
248         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
249             requestID == $event.getRequestId() )
250         $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
251             requestID == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
252     then
253
254     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
255     logger.info("{}: {}: event={} manager={} clTimer={}",
256                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
257                 $event, $manager, $clTimer);
258
259     try {
260         //
261         // Check which event this is.
262         //
263         ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event);
264         //
265         // Check what kind of event this is
266         //
267         if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) {
268             //
269             // We don't care about subsequent onsets
270             //
271             logger.info("{}: {}: subsequent onset",
272                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
273             retract($event);
274             return;
275         }
276         if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) {
277             //
278             // Ignore any bad syntax events
279             //
280             logger.warn("{}: {}: syntax error",
281                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
282             retract($event);
283             return;
284         }
285         //
286         // We only want the initial ONSET event in memory,
287         // all the other events need to be retracted to support
288         // cleanup and avoid the other rules being fired for this event.
289         //
290         if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) {
291             logger.warn("{}: {}: no first onset",
292                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
293             retract($event);
294         }
295
296         logger.debug("{}: {}: target={}", $clName,
297                      $params.getPolicyName() + "." + drools.getRule().getName(), $event.getTarget());
298         //
299         // Now start seeing if we need to process this event
300         //
301
302         //
303         // Check if this is a Final Event
304         //
305         VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
306
307
308         if (notification != null) {
309             //
310             // Its final, but are we waiting for abatement?
311             //
312             if ($manager.getNumAbatements() > 0) {
313                 logger.info("{}: {}: abatement received for {}.  Closing the control loop",
314                             $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
315                             $event.getRequestId());
316                 notification.setFrom("policy");
317                 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
318                 notification.setPolicyScope($params.getPolicyScope());
319                 notification.setPolicyVersion($params.getPolicyVersion());
320                 //
321                 // In this case, we are done
322                 //
323                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
324                 //
325                 // Unlock the target
326                 //
327                 TargetLock lock = $manager.unlockCurrentOperation();
328                 if (lock != null) {
329                     logger.debug("{}: {}: retracting lock=", $clName,
330                                  $params.getPolicyName() + "." + drools.getRule().getName(), lock);
331                     retract(lock);
332                 }
333                 //
334                 // Retract everything from memory
335                 //
336                 logger.info("{}: {}: retracting onset, manager, and timer",
337                             $clName, $params.getPolicyName() + "." + drools.getRule().getName());
338
339                 retract($manager.getOnsetEvent());
340                 
341                 // don't retract manager, etc. - a clean-up rule will do that
342                 
343                 //
344                 // TODO - what if we get subsequent Events for this RequestID?
345                 // By default, it will all start over again. May be confusing for Ruby.
346                 // Or, we could track this and then subsequently ignore the events
347                 //
348             } else {
349                 //
350                 // Check whether we need to wait for abatement
351                 //
352                 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
353                   logger.info("{}: {}: waiting for abatement ..",
354                               $clName, $params.getPolicyName() + "." + drools.getRule().getName());
355                 } else {
356                   logger.info("{}: {}: no abatement expect for {}.  Closing the control loop",
357                               $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
358                               $event.getRequestId());
359
360                   notification.setFrom("policy");
361                   notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
362                   notification.setPolicyScope($params.getPolicyScope());
363                   notification.setPolicyVersion($params.getPolicyVersion());
364
365                   //
366                   // In this case, we are done
367                   //
368                   PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
369                   //
370                   // Unlock the target
371                   //
372                   TargetLock lock = $manager.unlockCurrentOperation();
373                   if (lock != null) {
374                       logger.debug("{}: {}: retracting lock=", $clName,
375                                   $params.getPolicyName() + "." + drools.getRule().getName(), lock);
376                       retract(lock);
377                   }
378                   //
379                   // Retract everything from memory
380                   //
381                   logger.info("{}: {}: retracting onset, manager, and timer",
382                               $clName, $params.getPolicyName() + "." + drools.getRule().getName());
383
384                   retract($manager.getOnsetEvent());
385                 
386                   // don't retract manager, etc. - a clean-up rule will do that
387                 }
388             }
389         } else {
390             //
391             // NOT final, so let's ask for the next operation
392             //
393             ControlLoopOperationManager operation = $manager.processControlLoop();
394             if (operation != null) {
395               //
396               // Let's ask for a lock right away
397               //
398               LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
399               logger.info("{}: {}: guard lock acquired={}",
400                             $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
401                             result.getB());
402               if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
403                   //
404                   // insert the operation into memory
405                   //
406                   insert(operation);
407
408                   //
409                   // insert operation timeout object
410                   //
411                   ControlLoopTimer opTimer = new ControlLoopTimer();
412                   opTimer.setTimerType("Operation");
413                   opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
414                   opTimer.setRequestID($event.getRequestId().toString());
415                   opTimer.setDelay(operation.getOperationTimeout().toString() + "s");
416                   insert(opTimer);
417
418                   //
419                   // Insert lock into memory
420                   //
421                   insert(result.getB());
422               }
423               else {
424                   logger.debug("The target resource {} is already processing",
425                                 $event.getAai().get($event.getTarget()));
426                   notification = new VirtualControlLoopNotification($event);
427                   notification.setNotification(ControlLoopNotificationType.REJECTED);
428                   notification.setMessage("The target " + $event.getAai().get($event.getTarget()) 
429                       + " is already locked");
430                   notification.setFrom("policy");
431                   notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
432                   notification.setPolicyScope($params.getPolicyScope());
433                   notification.setPolicyVersion($params.getPolicyVersion());
434
435                   PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
436
437                   retract($event);
438                 
439                   // don't retract manager, etc. - a clean-up rule will do that
440
441                 if(result.getB() != null) {
442                   retract(result.getB());
443                 }
444               }
445               logger.info("{}: {}: starting operation={}",
446                           $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
447                           operation);
448             } else {
449               //
450               // Probably waiting for abatement
451               //
452               logger.info("{}: {}: no operation, probably waiting for abatement",
453                           $clName, $params.getPolicyName() + "." + drools.getRule().getName());
454             }
455         }
456     } catch (Exception e) {
457         logger.warn("{}: {}: unexpected",
458                    $clName,
459                    $params.getPolicyName() + "." + drools.getRule().getName(), e);
460
461         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
462         notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
463         notification.setMessage(e.getMessage());
464         notification.setFrom("policy");
465         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
466         notification.setPolicyScope($params.getPolicyScope());
467         notification.setPolicyVersion($params.getPolicyVersion());
468
469         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
470
471         retract($event);
472                 
473         // don't retract manager, etc. - a clean-up rule will do that
474     }
475
476 end
477
478 /*
479 *
480 * Guard Permitted, let's send request to the actor.
481 *
482 */
483 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
484     when
485         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
486         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
487         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
488             requestID == $event.getRequestId() )
489         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
490             onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
491         $lock : TargetLock (requestID == $event.getRequestId())
492         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
493             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
494     then
495
496     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
497     logger.info("{}: {}: event={} manager={} operation={} lock={}",
498                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
499                 $event, $manager, $operation, $lock);
500
501     Object request = null;
502     boolean caughtException = false;
503
504     try {
505         request = $operation.startOperation($event);
506
507         if (request != null) {
508           logger.debug("{}: {}: starting operation ..",
509                        $clName,
510                        $params.getPolicyName() + "." + drools.getRule().getName());
511           //
512           // Tell interested parties we are performing this Operation
513           //
514           VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
515           notification.setNotification(ControlLoopNotificationType.OPERATION);
516           notification.setMessage($operation.getOperationMessage());
517           notification.setHistory($operation.getHistory());
518           notification.setFrom("policy");
519           notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
520           notification.setPolicyScope($params.getPolicyScope());
521           notification.setPolicyVersion($params.getPolicyVersion());
522
523           PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
524
525           switch ($operation.policy.getActor()){
526
527               case "APPC":
528
529                   if (request instanceof Request) {
530                       PolicyEngine.manager.deliver("APPC-CL", request);
531                   }
532                   else if (request instanceof LcmRequestWrapper) {
533                       PolicyEngine.manager.deliver("APPC-LCM-READ", request);
534                   }
535                   break;
536               case "SO":
537                   // at this point the AAI named query request should have already been made, the response 
538                   // recieved and used in the construction of the SO Request which is stored in operationRequest
539
540                   if(request instanceof SORequest) {
541                       // Call SO. The response will be inserted into memory once it's received
542                       SoActorServiceProvider.sendRequest($event.getRequestId().toString(), drools.getWorkingMemory(), request);
543                   }
544                   break;
545               case "VFC":
546                   if (request instanceof VfcRequest) {
547                       // Start VFC thread
548                       Thread t = new Thread(new VfcManager(drools.getWorkingMemory(), (VfcRequest)request));
549                       t.start();
550                   }
551                   break;
552               case "SDNR":
553                   if (request instanceof PciRequestWrapper) {
554                       PolicyEngine.manager.deliver("SDNR-CL", request);
555                   }
556                   break;
557               
558               case "SDNC":
559                   if (request instanceof SdncRequest) {
560                      // Start SDNC thread
561                      Thread t = new Thread(new SdncManager(drools.getWorkingMemory(), (SdncRequest)request));
562                      t.start();
563                   }
564                   break;                 
565           }
566         } else {
567           //
568           // What happens if its null?
569           //
570             logger.warn("{}: {}: unexpected null operation request",
571                       $clName,
572                       $params.getPolicyName() + "." + drools.getRule().getName());
573             if ("SO".equals($operation.policy.getActor())) {
574                 retract($opTimer);
575                 retract($operation);
576                 modify($manager) {finishOperation($operation)};
577             }
578             else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
579                 retract($opTimer);
580                 retract($operation);
581                 modify($manager) {finishOperation($operation)};
582             }
583             else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
584                 retract($opTimer);
585                 retract($operation);
586                 modify($manager) {finishOperation($operation)};
587             }
588         }
589
590     } catch (Exception e) {
591         String msg = e.getMessage();
592         logger.warn("{}: {}: operation={}:  AAI failure: {}",
593                     $clName,
594                     $params.getPolicyName() + "." + drools.getRule().getName(),
595                     $operation, msg, e);
596         $operation.setOperationHasException(msg);
597
598         if(request != null) {
599             //
600             // Create a notification for it ("DB Write - end operation")
601             //
602             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
603             notification.setFrom("policy");
604             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
605             notification.setPolicyScope($params.getPolicyScope());
606             notification.setPolicyVersion($params.getPolicyVersion());
607             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
608             notification.setMessage($operation.getOperationHistory());
609             notification.setHistory($operation.getHistory());
610
611             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
612         }
613
614         retract($opTimer);
615         retract($operation);
616         caughtException = true;
617     }
618
619     // Having the modify statement in the catch clause doesn't work for whatever reason
620     if (caughtException) {
621         modify($manager) {finishOperation($operation)};
622     }
623 end
624
625
626 /*
627 *
628 * We were able to acquire a lock so now let's ask Xacml Guard whether
629 * we are allowed to proceed with the request to the actor.
630 *
631 */
632 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
633     when
634         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
635         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
636         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
637             requestID == $event.getRequestId() )
638         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
639             onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
640         $lock : TargetLock (requestID == $event.getRequestId())
641     then
642
643     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
644     logger.info("{}: {}: event={} manager={} operation={} lock={}",
645                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
646                 $event, $manager, $operation, $lock);
647
648     //
649     // Sending notification that we are about to query Guard ("DB write - start operation")
650     //
651     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
652     notification.setNotification(ControlLoopNotificationType.OPERATION);
653     notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " " 
654         + $operation.policy.getRecipe());
655     notification.setHistory($operation.getHistory());
656     notification.setFrom("policy");
657     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
658     notification.setPolicyScope($params.getPolicyScope());
659     notification.setPolicyVersion($params.getPolicyVersion());
660
661     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
662
663     //
664     // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
665     // just change guardEnabled to false.
666     //
667     // In order to use REST XACML, provide a URL instead of "" as a second argument
668     // to the CallGuardTask() and set the first argument to null
669     // (instead of XacmlPdpEngine).
670     //
671
672     // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
673     boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
674
675     if(guardEnabled){
676
677         Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
678                                                         drools.getWorkingMemory(),
679                                                         $event.getClosedLoopControlName(),
680                                                         $operation.policy.getActor().toString(),
681                                                         $operation.policy.getRecipe(),
682                                                         $operation.getTargetEntity(),
683                                                         $event.getRequestId().toString(),
684                                                         () -> {
685                                                             AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
686                                                             return(resp == null ? null : resp.countVfModules());
687                                                         }));
688         t.start();
689     }
690     else{
691         insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
692     }
693
694 end
695
696 //
697 // This rule will be triggered when a thread talking to the XACML Guard inserts a
698 // guardResponse object into the working memory
699 //
700 rule "GUARD.RESPONSE"
701     when
702         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
703         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
704             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
705         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
706             requestID == $event.getRequestId() )
707         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
708             onset.getRequestId() == $event.getRequestId() )
709         $lock : TargetLock (requestID == $event.getRequestId())
710         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
711             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
712         $guardResponse : PolicyGuardResponse(requestID == $event.getRequestId(), $operation.policy.recipe == operation)
713     then
714
715     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
716     logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
717                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
718                  $event, $manager, $operation, $lock, $opTimer, $guardResponse);
719
720
721     //we will permit the operation if there was no Guard for it
722     if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
723         $guardResponse.setResult("Permit");
724     }
725
726     //
727     // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
728     //
729     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
730     notification.setNotification(ControlLoopNotificationType.OPERATION);
731     notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
732         + " is " + $guardResponse.getResult());
733     notification.setHistory($operation.getHistory());
734     notification.setFrom("policy");
735     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
736     notification.setPolicyScope($params.getPolicyScope());
737     notification.setPolicyVersion($params.getPolicyVersion());
738
739     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
740
741     if("Permit".equalsIgnoreCase($guardResponse.getResult())){
742
743         modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
744     }
745     else {
746         //This is the Deny case
747         $operation.startOperation($event);
748         $operation.setOperationHasGuardDeny();
749         retract($opTimer);
750         retract($operation);
751         modify($manager) {finishOperation($operation)};
752     }
753
754     retract($guardResponse);
755
756 end
757
758 /*
759 *
760 * This rule responds to APPC Response Events
761 *
762 * I would have like to be consistent and write the Response like this:
763 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
764 *
765 * However, no compile error was given. But a runtime error was given. I think
766 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
767 *
768 */
769 rule "APPC.RESPONSE"
770     when
771         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
772         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
773             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
774         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
775             requestID == $event.getRequestId() )
776         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
777             onset.getRequestId() == $event.getRequestId() )
778         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
779             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
780         $lock : TargetLock (requestID == $event.getRequestId())
781         $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
782     then
783
784     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
785     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
786     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
787                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
788                  $event, $manager, $operation, $lock, $opTimer, $response);
789     //
790     // Get the result of the operation
791     //
792     PolicyResult policyResult = $operation.onResponse($response);
793     if (policyResult != null) {
794         logger.debug("{}: {}: operation finished - result={}",
795                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
796                     policyResult);
797         //
798         // This Operation has completed, construct a notification showing our results. (DB write - end operation)
799         //
800         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
801         notification.setFrom("policy");
802         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
803         notification.setPolicyScope($params.getPolicyScope());
804         notification.setPolicyVersion($params.getPolicyVersion());
805         notification.setMessage($operation.getOperationHistory());
806         notification.setHistory($operation.getHistory());
807         if (policyResult.equals(PolicyResult.SUCCESS)) {
808             notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
809             //
810             // Let interested parties know
811             //
812             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
813         } else {
814             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
815             //
816             // Let interested parties know
817             //
818             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
819         }
820         //
821         // Ensure the operation is complete
822         //
823         if ($operation.isOperationComplete() == true) {
824             //
825             // It is complete, remove it from memory
826             //
827             retract($operation);
828             //
829             // We must also retract the timer object
830             // NOTE: We could write a Rule to do this
831             //
832             retract($opTimer);
833             //
834             // Complete the operation
835             //
836             modify($manager) {finishOperation($operation)};
837         } else {
838             //
839             // Just doing this will kick off the LOCKED rule again
840             //
841             modify($operation) {};
842         }
843     } else {
844         //
845         // Its not finished yet (i.e. expecting more Response objects)
846         //
847         // Or possibly it is a leftover response that we timed the request out previously
848         //
849     }
850     //
851     // We are going to retract these objects from memory
852     //
853     retract($response);
854 end
855
856 /*
857 *
858 * The problem with Responses is that they don't have a controlLoopControlName
859 * field in them, so the only way to attach them is via RequestID. If we have multiple
860 * control loop .drl's loaded in the same container, we need to be sure the cleanup
861 * rules don't remove Responses for other control loops.
862 *
863 */
864 rule "APPC.RESPONSE.CLEANUP"
865     when
866         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
867         $response : Response($id : getCommonHeader().RequestId )
868         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
869     then
870
871     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
872     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
873     logger.debug("{}: {}: orphan appc response={}",
874                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
875
876     //
877     // Retract it
878     //
879     retract($response);
880 end
881
882 /*
883 *
884 * This rule responds to APPC Response Events using the new LCM interface provided by appc
885 *
886 */
887 rule "APPC.LCM.RESPONSE"
888     when
889         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
890         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
891             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
892         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
893             requestID == $event.getRequestId() )
894         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
895             onset.getRequestId() == $event.getRequestId() )
896         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
897             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
898         $lock : TargetLock (requestID == $event.getRequestId())
899         $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
900     then
901
902     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
903     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
904     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
905                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
906                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
907
908     //
909     // Get the result of the operation
910     //
911     PolicyResult policyResult = $operation.onResponse($response);
912     if (policyResult != null) {
913       logger.debug("{}: {}: operation finished - result={}",
914                   $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
915                   policyResult);
916
917       //
918       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
919       //
920       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
921       notification.setFrom("policy");
922       notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
923       notification.setPolicyScope($params.getPolicyScope());
924       notification.setPolicyVersion($params.getPolicyVersion());
925       notification.setMessage($operation.getOperationHistory());
926       notification.setHistory($operation.getHistory());
927       if (policyResult.equals(PolicyResult.SUCCESS)) {
928           notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
929       } else {
930           notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
931       }
932       PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
933       //
934       // Ensure the operation is complete
935       //
936       if ($operation.isOperationComplete() == true) {
937           //
938           // It is complete, remove it from memory
939           //
940           retract($operation);
941           //
942           // We must also retract the timer object
943           // NOTE: We could write a Rule to do this
944           //
945           retract($opTimer);
946           //
947           // Complete the operation
948           //
949           modify($manager) {finishOperation($operation)};
950       } else {
951           //
952           // Just doing this will kick off the LOCKED rule again
953           //
954           modify($operation) {};
955       }
956     } else {
957         //
958         // Its not finished yet (i.e. expecting more Response objects)
959         //
960         // Or possibly it is a leftover response that we timed the request out previously
961         //
962     }
963     //
964     // We are going to retract these objects from memory
965     //
966     retract($response);
967 end
968
969 /*
970 *
971 * Clean Up any lingering LCM reponses
972 *
973 */
974 rule "APPC.LCM.RESPONSE.CLEANUP"
975     when
976         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
977         $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
978         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
979     then
980
981     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
982     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
983     logger.debug("{}: {}: orphan appc response={}",
984                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
985     //
986     // Retract it
987     //
988     retract($response);
989 end
990
991 /*
992 *
993 * This rule responds to SO Response Events
994 *
995 */
996 rule "SO.RESPONSE"
997     when
998         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
999         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1000             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1001         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1002             requestID == $event.getRequestId() )
1003         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1004             onset.getRequestId() == $event.getRequestId() )
1005         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1006             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1007         $lock : TargetLock (requestID == $event.getRequestId())
1008         $response : SOResponseWrapper(requestID.toString() == $event.getRequestId().toString() )
1009     then
1010
1011     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1012     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1013     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1014                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1015                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1016
1017     // Get the result of the operation
1018     //
1019     PolicyResult policyResult = $operation.onResponse($response);
1020     if (policyResult != null) {
1021         logger.debug("{}: {}: operation finished - result={}",
1022                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1023                     policyResult);
1024
1025         //
1026         // This Operation has completed, construct a notification showing our results
1027         //
1028         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1029         notification.setFrom("policy");
1030         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1031         notification.setPolicyScope($params.getPolicyScope());
1032         notification.setPolicyVersion($params.getPolicyVersion());
1033         notification.setMessage($operation.getOperationHistory());
1034         notification.setHistory($operation.getHistory());
1035         if (policyResult.equals(PolicyResult.SUCCESS)) {
1036             notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1037         } else {
1038             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1039
1040         }
1041         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1042         //
1043         // Ensure the operation is complete
1044         //
1045         if ($operation.isOperationComplete() == true) {
1046             //
1047             // It is complete, remove it from memory
1048             //
1049             retract($operation);
1050             //
1051             // We must also retract the timer object
1052             // NOTE: We could write a Rule to do this
1053             //
1054             retract($opTimer);
1055             //
1056             // Complete the operation
1057             //
1058             modify($manager) {finishOperation($operation)};
1059         } else {
1060             //
1061             // Just doing this will kick off the LOCKED rule again
1062             //
1063             modify($operation) {};
1064         }
1065     } else {
1066         //
1067         // Its not finished yet (i.e. expecting more Response objects)
1068         //
1069         // Or possibly it is a leftover response that we timed the request out previously
1070         //
1071     }
1072     //
1073     // We are going to retract these objects from memory
1074     //
1075     retract($response);
1076
1077 end
1078
1079 /*
1080 *
1081 * This rule responds to VFC Response Events
1082 *
1083 */
1084 rule "VFC.RESPONSE"
1085     when
1086         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1087         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1088             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1089         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1090             requestID == $event.getRequestId() )
1091         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1092             onset.getRequestId() == $event.getRequestId() )
1093         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1094             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1095         $lock : TargetLock (requestID == $event.getRequestId())
1096         $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1097     then
1098         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1099         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1100         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1101                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1102                     $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1103
1104         // Get the result of the operation
1105         //
1106         PolicyResult policyResult = $operation.onResponse($response);
1107         if (policyResult != null) {
1108             //
1109             // This Operation has completed, construct a notification showing our results
1110             //
1111             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1112             notification.setFrom("policy");
1113             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1114             notification.setPolicyScope($params.getPolicyScope());
1115             notification.setPolicyVersion($params.getPolicyVersion());
1116             notification.setMessage($operation.getOperationHistory());
1117             notification.setHistory($operation.getHistory());
1118             //
1119             // Ensure the operation is complete
1120             //
1121             if ($operation.isOperationComplete() == true) {
1122                 //
1123                 // It is complete, remove it from memory
1124                 //
1125                 retract($operation);
1126                 //
1127                 // We must also retract the timer object
1128                 // NOTE: We could write a Rule to do this
1129                 //
1130                 retract($opTimer);
1131                 //
1132                 // Complete the operation
1133                 //
1134                 modify($manager) {finishOperation($operation)};
1135             } else {
1136                 //
1137                 // Just doing this will kick off the LOCKED rule again
1138                 //
1139                 modify($operation) {};
1140             }
1141         } else {
1142             //
1143             // Its not finished yet (i.e. expecting more Response objects)
1144             //
1145             // Or possibly it is a leftover response that we timed the request out previously
1146             //
1147         }
1148         //
1149         // We are going to retract these objects from memory
1150         //
1151         retract($response);
1152
1153 end
1154
1155 /*
1156 *
1157 * This rule responds to SDNC Response Events
1158 *
1159 */
1160 rule "SDNC.RESPONSE"
1161     when
1162         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1163         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1164         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() )
1165         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId() )
1166         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1167             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1168         $lock : TargetLock (requestID == $event.getRequestId())
1169         $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1170     then
1171         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1172         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1173         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1174                         $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1175                         $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1176
1177         // Get the result of the operation
1178         //
1179         PolicyResult policyResult = $operation.onResponse($response);
1180         if (policyResult != null) {
1181             //
1182             // This Operation has completed, construct a notification showing our results
1183             //
1184             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1185             notification.setFrom("policy");
1186             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1187             notification.setPolicyScope($params.getPolicyScope());
1188             notification.setPolicyVersion($params.getPolicyVersion());
1189             notification.setMessage($operation.getOperationHistory());
1190             notification.setHistory($operation.getHistory());
1191             //
1192             // Ensure the operation is complete
1193             //
1194             if ($operation.isOperationComplete()) {
1195                 //
1196                 // It is complete, remove it from memory
1197                 //
1198                 retract($operation);
1199                 //
1200                 // We must also retract the timer object
1201                 // NOTE: We could write a Rule to do this
1202                 //
1203                 retract($opTimer);
1204                 //
1205                 // Complete the operation
1206                 //
1207                 modify($manager) {finishOperation($operation)};
1208             } else {
1209                 //
1210                 // Just doing this will kick off the LOCKED rule again
1211                 //
1212                 modify($operation) {};
1213             }
1214         } else {
1215             //
1216             // Its not finished yet (i.e. expecting more Response objects)
1217             //
1218             // Or possibly it is a leftover response that we timed the request out previously
1219             //
1220         }
1221         //
1222         // We are going to retract these objects from memory
1223         //
1224         retract($response);
1225
1226 end
1227
1228 /*
1229 *
1230 * This manages a single timer.
1231 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1232 *
1233 */
1234 rule "TIMER.FIRED"
1235     timer (expr: $timeout)
1236     when
1237         $timer : ControlLoopTimer($timeout : delay, !expired)
1238     then
1239         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1240         logger.info("This is TIMER.FIRED");
1241         modify($timer){setExpired(true)};
1242     end
1243
1244 /*
1245 *
1246 * This is the timer that manages the timeout for an individual operation.
1247 *
1248 */
1249 rule "EVENT.MANAGER.OPERATION.TIMEOUT"
1250     when
1251         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1252         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1253         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1254             requestID == $event.getRequestId() )
1255         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1256             onset.getRequestId() == $event.getRequestId() )
1257         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1258             requestID == $event.getRequestId().toString(), timerType == "Operation", expired )
1259         $lock : TargetLock (requestID == $event.getRequestId())
1260     then
1261
1262     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1263     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1264     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1265                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1266                 $event, $manager, $operation, $lock, $operation, $opTimer);
1267
1268     //
1269     // Tell it its timed out
1270     //
1271     $operation.setOperationHasTimedOut();
1272     //
1273     // Create a notification for it ("DB Write - end operation")
1274     //
1275     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1276     notification.setFrom("policy");
1277     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1278     notification.setPolicyScope($params.getPolicyScope());
1279     notification.setPolicyVersion($params.getPolicyVersion());
1280     notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1281     notification.setMessage($operation.getOperationHistory());
1282     notification.setHistory($operation.getHistory());
1283     //
1284     // Let interested parties know
1285     //
1286     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1287     //
1288     // Get rid of the timer
1289     //
1290     retract($opTimer);
1291     //
1292     // Ensure the operation is complete
1293     //
1294     if ($operation.isOperationComplete() == true) {
1295         //
1296         // It is complete, remove it from memory
1297         //
1298         retract($operation);
1299         //
1300         // Complete the operation
1301         //
1302         modify($manager) {finishOperation($operation)};
1303     } else {
1304         //
1305         // Just doing this will kick off the LOCKED rule again
1306         //
1307         modify($operation) {};
1308     }
1309 end
1310
1311 /*
1312 *
1313 * This is the timer that manages the overall control loop timeout.
1314 *
1315 */
1316 rule "EVENT.MANAGER.TIMEOUT"
1317     when
1318         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1319         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1320         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1321             requestID == $event.getRequestId() )
1322         $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1323             requestID == $event.getRequestId().toString(), timerType == "ClosedLoop", expired )
1324     then
1325
1326     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1327     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1328
1329     logger.debug("{}: {}: event={}",
1330               $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1331               $event);
1332     //
1333     // Tell the Event Manager it has timed out
1334     //
1335     VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1336     if (notification != null) {
1337         notification.setFrom("policy");
1338         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1339         notification.setPolicyScope($params.getPolicyScope());
1340         notification.setPolicyVersion($params.getPolicyVersion());
1341         //
1342         // Let interested parties know
1343         //
1344         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1345     }
1346     //
1347     // Retract the event
1348     //
1349     retract($event);
1350 end
1351
1352 /*
1353 *
1354 * This rule cleans up the manager and other objects after an event has
1355 * been retracted.
1356 *
1357 */
1358 rule "EVENT.MANAGER.CLEANUP"
1359     when
1360         $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestID() )
1361         $operations : LinkedList()
1362                         from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName, 
1363                             onset.getRequestId() == $requestId ) )
1364         $timers : LinkedList()
1365                         from collect( ControlLoopTimer( closedLoopControlName == $clName, 
1366                             requestID == $requestId.toString() ) )
1367         $locks : LinkedList()
1368                         from collect( TargetLock (requestID == $requestId) )
1369         not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1370     then
1371
1372     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1373     logger.info("{}: {}", $clName, drools.getRule().getName());
1374
1375     logger.debug("{}: {}: manager={} timers={} operations={}",
1376               $clName, drools.getRule().getName(),
1377               $manager, $timers.size(), $operations.size());
1378
1379     //
1380     // Retract EVERYTHING
1381     //
1382     retract($manager);
1383
1384     for(Object manager: $operations) {
1385         retract((ControlLoopOperationManager) manager);
1386     }
1387     for(Object timer: $timers) {
1388         retract((ControlLoopTimer) timer);
1389     }
1390     for(Object lock: $locks) {
1391         TargetLock tgt = (TargetLock) lock;
1392         //
1393         // Ensure we release the lock
1394         //
1395         PolicyGuard.unlockTarget(tgt);
1396         retract(tgt);
1397     }
1398 end
1399
1400 /*
1401 *
1402 * This rule will clean up any rogue onsets where there is no
1403 * ControlLoopParams object corresponding to the onset event.
1404 *
1405 */
1406 rule "EVENT.CLEANUP"
1407     when
1408         $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1409         not ( ControlLoopParams( getClosedLoopControlName() == $clName) )
1410     then
1411
1412     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1413     logger.info("{}: {}", $clName, drools.getRule().getName());
1414     logger.debug("{}: {}: orphan onset event={}",
1415                 $clName, drools.getRule().getName(), $event);
1416
1417     retract($event);
1418 end
1419
1420 /*
1421 *
1422 * This rule responds to SDNR Response Events.
1423 *
1424 */
1425 rule "SDNR.RESPONSE"
1426     when
1427         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1428         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1429             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1430         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1431             requestID == $event.getRequestId() )
1432         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1433             onset.getRequestId() == $event.getRequestId() )
1434         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1435             requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1436         $lock : TargetLock (requestID == $event.getRequestId())
1437         $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1438     then
1439
1440     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1441     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1442     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1443                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1444                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1445
1446     //
1447     // Get the result of the operation
1448     //
1449     PolicyResult policyResult = $operation.onResponse($response);
1450     if (policyResult != null) {
1451       logger.debug("{}: {}: operation finished - result={}",
1452                   $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1453                   policyResult);
1454
1455       //
1456       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1457       //
1458       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1459       notification.setFrom("policy");
1460       notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1461       notification.setPolicyScope($params.getPolicyScope());
1462       notification.setPolicyVersion($params.getPolicyVersion());
1463       notification.setMessage($operation.getOperationHistory());
1464       notification.setHistory($operation.getHistory());
1465       if (policyResult.equals(PolicyResult.SUCCESS)) {
1466           notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1467       } else {
1468           notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1469       }
1470       PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1471       //
1472       // Ensure the operation is complete
1473       //
1474       if ($operation.isOperationComplete() == true) {
1475           //
1476           // It is complete, remove it from memory
1477           //
1478           retract($operation);
1479           //
1480           // We must also retract the timer object
1481           // NOTE: We could write a Rule to do this
1482           //
1483           retract($opTimer);
1484           //
1485           // Complete the operation
1486           //
1487           modify($manager) {finishOperation($operation)};
1488       } else {
1489           //
1490           // Just doing this will kick off the LOCKED rule again
1491           //
1492           modify($operation) {};
1493       }
1494     } else {
1495         //
1496         // Its not finished yet (i.e. expecting more Response objects)
1497         //
1498         // Or possibly it is a leftover response that we timed the request out previously
1499         //
1500     }
1501     //
1502     // We are going to retract these objects from memory
1503     //
1504     retract($response);
1505 end
1506
1507 /*
1508 *
1509 * Clean Up any lingering SDNR reponses.
1510 *
1511 */
1512 rule "SDNR.RESPONSE.CLEANUP"
1513     when
1514         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1515         $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1516         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1517     then
1518
1519     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1520     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1521     logger.debug("{}: {}: orphan sdnr response={}",
1522                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
1523     //
1524     // Retract it
1525     //
1526     retract($response);
1527 end