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