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