0352dec107b314b61eaa4e13e50e9681176be4d6
[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.aai.AaiNqResponseWrapper;
37 import org.onap.policy.appc.Request;
38 import org.onap.policy.appc.Response;
39 import org.onap.policy.appc.CommonHeader;
40 import org.onap.policy.appclcm.LcmRequestWrapper;
41 import org.onap.policy.appclcm.LcmResponseWrapper;
42 import org.onap.policy.appclcm.LcmRequest;
43 import org.onap.policy.appclcm.LcmResponse;
44 import org.onap.policy.appclcm.LcmCommonHeader;
45 import org.onap.policy.vfc.VFCRequest;
46 import org.onap.policy.vfc.VFCResponse;
47 import org.onap.policy.vfc.VFCManager;
48 import org.onap.policy.so.SOManager;
49 import org.onap.policy.so.SORequest;
50 import org.onap.policy.so.SORequestStatus;
51 import org.onap.policy.so.SORequestDetails;
52 import org.onap.policy.so.SOModelInfo;
53 import org.onap.policy.so.SOCloudConfiguration;
54 import org.onap.policy.so.SORequestInfo;
55 import org.onap.policy.so.SORequestParameters;
56 import org.onap.policy.so.SORelatedInstanceListElement;
57 import org.onap.policy.so.SORelatedInstance;
58 import org.onap.policy.so.SOResponse;
59 import org.onap.policy.so.SOResponseWrapper;
60 import org.onap.policy.guard.PolicyGuard;
61 import org.onap.policy.guard.PolicyGuard.LockResult;
62 import org.onap.policy.guard.TargetLock;
63 import org.onap.policy.guard.GuardResult;
64 import org.onap.policy.guard.PolicyGuardRequest;
65 import org.onap.policy.guard.PolicyGuardResponse;
66 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
67 import org.onap.policy.guard.PolicyGuardXacmlHelper;
68
69 import org.yaml.snakeyaml.Yaml;
70 import org.yaml.snakeyaml.constructor.Constructor;
71
72 import org.slf4j.LoggerFactory;
73 import org.slf4j.Logger;
74
75 import java.time.Instant;
76 import java.util.LinkedList;
77 import java.util.Iterator;
78
79 import org.onap.policy.drools.system.PolicyEngine;
80
81 /*
82  * Operation Timer
83  */
84 declare OperationTimer
85   closedLoopControlName : String
86   requestID : String
87   delay : String
88 end
89
90 /*
91  * Control Loop Timer
92  */
93 declare ControlLoopTimer
94   closedLoopControlName : String
95   requestID : String
96   delay : String
97 end
98
99 /*
100 *
101 * Called when the ControlLoopParams object has been inserted into working memory from the BRMSGW.
102 *
103 */
104 rule "INSERT.PARAMS"
105     when
106         $params : ControlLoopParams()
107     then
108
109     // Note: globals have bad behavior when persistence is used,
110     //       hence explicitly getting the logger vs using a global
111
112     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
113     logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "." + drools.getRule().getName(), $params.getControlLoopYaml());
114 end
115
116 /*
117 *
118 * This rule responds to DCAE Events where there is no manager yet. Either it is
119 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
120 *
121 */
122 rule "EVENT"
123     when
124         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
125         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
126         not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() ) )
127     then
128
129     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
130     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
131
132     try {
133
134         //
135         // Check the event, because we need it to not be null when
136         // we create the ControlLoopEventManager. The ControlLoopEventManager
137         // will do extra syntax checking as well check if the closed loop is disabled.
138         //
139         if ($event.getRequestId() == null) {
140             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
141             notification.setNotification(ControlLoopNotificationType.REJECTED);
142             notification.setFrom("policy");
143             notification.setMessage("Missing requestID");
144             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
145             notification.setPolicyScope($params.getPolicyScope());
146             notification.setPolicyVersion($params.getPolicyVersion());
147
148             //
149             // Let interested parties know
150             //
151             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
152
153             //
154             // Retract it from memory
155             //
156             retract($event);
157         } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
158             throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
159         } else {
160             //
161             // Create an EventManager
162             //
163             ControlLoopEventManager manager = new ControlLoopEventManager($clName, $event.getRequestId());
164             //
165             // Determine if EventManager can actively process the event (i.e. syntax, is_closed_loop_disabled checks etc.)
166             //
167             VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
168             notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
169             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
170             notification.setPolicyScope($params.getPolicyScope());
171             notification.setPolicyVersion($params.getPolicyVersion());
172             //
173             // Are we actively pursuing this event?
174             //
175             if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
176                 //
177                 // Insert Event Manager into memory, this will now kick off processing.
178                 //
179                 insert(manager);
180                 //
181                 // Let interested parties know
182                 //
183                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
184                 //
185                 // Setup the Overall Control Loop timer
186                 //
187                 ControlLoopTimer clTimer = new ControlLoopTimer();
188                 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
189                 clTimer.setRequestID($event.getRequestId().toString());
190                 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
191                 //
192                 // Insert it
193                 //
194                 insert(clTimer);
195             } else {
196                 //
197                 // Let interested parties know
198                 //
199                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
200                 //
201                 // Retract it from memory
202                 //
203                 retract($event);
204             }
205
206             //
207             // Now that the manager is inserted into Drools working memory, we'll wait for
208             // another rule to fire in order to continue processing. This way we can also
209             // then screen for additional ONSET and ABATED events for this RequestID.
210             //
211         }
212     } catch (Exception e) {
213         logger.warn("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName(), e);
214
215         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
216         notification.setNotification(ControlLoopNotificationType.REJECTED);
217         notification.setMessage("Exception occurred: " + e.getMessage());
218         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
219         notification.setPolicyScope($params.getPolicyScope());
220         notification.setPolicyVersion($params.getPolicyVersion());
221         //
222         //
223         //
224         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
225         //
226         // Retract the event
227         //
228         retract($event);
229     }
230 end
231
232 /*
233 *
234 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
235 * is now created. We can start processing the yaml specification via the Event Manager.
236 *
237 */
238 rule "EVENT.MANAGER"
239     when
240         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
241         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
242         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() )
243         $clTimer : ControlLoopTimer ( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId().toString() )
244     then
245
246     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
247     logger.info("{}: {}: event={} manager={} clTimer={}",
248                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
249                 $event, $manager, $clTimer);
250
251     try {
252         //
253         // Check which event this is.
254         //
255         ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event);
256         //
257         // Check what kind of event this is
258         //
259         if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) {
260             //
261             // We don't care about subsequent onsets
262             //
263             logger.info("{}: {}: subsequent onset",
264                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
265             retract($event);
266             return;
267         }
268         if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) {
269             //
270             // Ignore any bad syntax events
271             //
272             logger.warn("{}: {}: syntax error",
273                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
274             retract($event);
275             return;
276         }
277         //
278         // We only want the initial ONSET event in memory,
279         // all the other events need to be retracted to support
280         // cleanup and avoid the other rules being fired for this event.
281         //
282         if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) {
283             logger.warn("{}: {}: no first onset",
284                         $clName, $params.getPolicyName() + "." + drools.getRule().getName());
285             retract($event);
286         }
287
288         logger.debug("{}: {}: target={}", $clName,
289                      $params.getPolicyName() + "." + drools.getRule().getName(), $event.getTarget());
290         //
291         // Now start seeing if we need to process this event
292         //
293
294         //
295         // Check if this is a Final Event
296         //
297         VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
298
299
300         if (notification != null) {
301             //
302             // Its final, but are we waiting for abatement?
303             //
304             if ($manager.getNumAbatements() > 0) {
305                 logger.info("{}: {}: abatement received for {}.  Closing the control loop",
306                             $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
307                             $event.getRequestId());
308                 notification.setFrom("policy");
309                 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
310                 notification.setPolicyScope($params.getPolicyScope());
311                 notification.setPolicyVersion($params.getPolicyVersion());
312                 //
313                 // In this case, we are done
314                 //
315                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
316                 //
317                 // Unlock the target
318                 //
319                 TargetLock lock = $manager.unlockCurrentOperation();
320                 if (lock != null) {
321                     logger.debug("{}: {}: retracting lock=", $clName,
322                                  $params.getPolicyName() + "." + drools.getRule().getName(), lock);
323                     retract(lock);
324                 }
325                 //
326                 // Retract everything from memory
327                 //
328                 logger.info("{}: {}: retracting onset, manager, and timer",
329                             $clName, $params.getPolicyName() + "." + drools.getRule().getName());
330
331                 retract($manager.getOnsetEvent());
332                 retract($manager);
333                 retract($clTimer);
334                 //
335                 // TODO - what if we get subsequent Events for this RequestID?
336                 // By default, it will all start over again. May be confusing for Ruby.
337                 // Or, we could track this and then subsequently ignore the events
338                 //
339             } else {
340                 //
341                 // Check whether we need to wait for abatement
342                 //
343                 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
344                   logger.info("{}: {}: waiting for abatement ..",
345                               $clName, $params.getPolicyName() + "." + drools.getRule().getName());
346                 } else {
347                   logger.info("{}: {}: no abatement expect for {}.  Closing the control loop",
348                               $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
349                               $event.getRequestId());
350
351                   notification.setFrom("policy");
352                   notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
353                   notification.setPolicyScope($params.getPolicyScope());
354                   notification.setPolicyVersion($params.getPolicyVersion());
355
356                   //
357                   // In this case, we are done
358                   //
359                   PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
360                   //
361                   // Unlock the target
362                   //
363                   TargetLock lock = $manager.unlockCurrentOperation();
364                   if (lock != null) {
365                       logger.debug("{}: {}: retracting lock=", $clName,
366                                   $params.getPolicyName() + "." + drools.getRule().getName(), lock);
367                       retract(lock);
368                   }
369                   //
370                   // Retract everything from memory
371                   //
372                   logger.info("{}: {}: retracting onset, manager, and timer",
373                               $clName, $params.getPolicyName() + "." + drools.getRule().getName());
374
375                   retract($manager.getOnsetEvent());
376                   retract($manager);
377                   retract($clTimer);
378                 }
379             }
380         } else {
381             //
382             // NOT final, so let's ask for the next operation
383             //
384             ControlLoopOperationManager operation = $manager.processControlLoop();
385             if (operation != null) {
386               //
387               // Let's ask for a lock right away
388               //
389               LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
390               logger.info("{}: {}: guard lock acquired={}",
391                             $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
392                             result.getB());
393               if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
394                   //
395                   // insert the operation into memory
396                   //
397                   insert(operation);
398
399                   //
400                   // insert operation timeout object
401                   //
402                   OperationTimer opTimer = new OperationTimer();
403                   opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
404                   opTimer.setRequestID($event.getRequestId().toString());
405                   opTimer.setDelay(operation.getOperationTimeout().toString() + "s");
406                   insert(opTimer);
407
408                   //
409                   // Insert lock into memory
410                   //
411                   insert(result.getB());
412               }
413               else {
414                   logger.debug("The target resource {} is already processing",
415                                 $event.getAai().get($event.getTarget()));
416                   notification = new VirtualControlLoopNotification($event);
417                   notification.setNotification(ControlLoopNotificationType.REJECTED);
418                   notification.setMessage("The target " + $event.getAai().get($event.getTarget()) + " is already locked");
419                   notification.setFrom("policy");
420                   notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
421                   notification.setPolicyScope($params.getPolicyScope());
422                   notification.setPolicyVersion($params.getPolicyVersion());
423
424                   PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
425
426                   retract($event);
427                   retract($manager);
428                   retract($clTimer);
429
430                 if(result.getB() != null) {
431                   retract(result.getB());
432                 }
433               }
434               logger.info("{}: {}: starting operation={}",
435                           $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
436                           operation);
437             } else {
438               //
439               // Probably waiting for abatement
440               //
441               logger.info("{}: {}: no operation, probably waiting for abatement",
442                           $clName, $params.getPolicyName() + "." + drools.getRule().getName());
443             }
444         }
445     } catch (Exception e) {
446         logger.warn("{}: {}: unexpected",
447                         $clName,
448                         $params.getPolicyName() + "." + drools.getRule().getName(), e);
449
450         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
451         notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
452         notification.setMessage(e.getMessage());
453         notification.setFrom("policy");
454         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
455         notification.setPolicyScope($params.getPolicyScope());
456         notification.setPolicyVersion($params.getPolicyVersion());
457
458         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
459
460         retract($event);
461         retract($manager);
462         retract($clTimer);
463     }
464
465 end
466
467 /*
468 *
469 * Guard Permitted, let's send request to the actor.
470 *
471 */
472 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
473     when
474         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
475         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
476         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() )
477         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
478         $lock : TargetLock (requestID == $event.getRequestId())
479         $opTimer : OperationTimer( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId().toString() )
480     then
481
482     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
483     logger.info("{}: {}: event={} manager={} operation={} lock={}",
484                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
485                 $event, $manager, $operation, $lock);
486
487     Object request = null;
488     boolean caughtException = false;
489
490     try {
491         request = $operation.startOperation($event);
492
493         if (request != null) {
494           logger.debug("{}: {}: starting operation ..",
495                        $clName,
496                        $params.getPolicyName() + "." + drools.getRule().getName());
497           //
498           // Tell interested parties we are performing this Operation
499           //
500           VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
501           notification.setNotification(ControlLoopNotificationType.OPERATION);
502           notification.setMessage($operation.getOperationMessage());
503           notification.setHistory($operation.getHistory());
504           notification.setFrom("policy");
505           notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
506           notification.setPolicyScope($params.getPolicyScope());
507           notification.setPolicyVersion($params.getPolicyVersion());
508
509           PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
510
511           switch ($operation.policy.getActor()){
512
513               case "APPC":
514
515                   if (request instanceof Request) {
516                       PolicyEngine.manager.deliver("APPC-CL", request);
517                   }
518                   else if (request instanceof LcmRequestWrapper) {
519                       PolicyEngine.manager.deliver("APPC-LCM-READ", request);
520                   }
521                   break;
522               case "SO":
523                   // at this point the AAI named query request should have already been made, the response recieved and used
524                   // in the construction of the SO Request which is stored in operationRequest
525
526                   if(request instanceof SORequest) {
527                       // Call SO. The response will be inserted into memory once it's received
528                       SOActorServiceProvider.sendRequest($event.getRequestId().toString(), drools.getWorkingMemory(), request);
529                   }
530                   break;
531               case "VFC":
532                   if (request instanceof VFCRequest) {
533                       // Start VFC thread
534                       Thread t = new Thread(new VFCManager(drools.getWorkingMemory(), (VFCRequest)request));
535                       t.start();
536                   }
537                   break;
538           }
539         } else {
540           //
541           // What happens if its null?
542           //
543             logger.warn("{}: {}: unexpected null operation request",
544                       $clName,
545                       $params.getPolicyName() + "." + drools.getRule().getName());
546             if ("SO".equals($operation.policy.getActor())) {
547                 retract($opTimer);
548                 retract($operation);
549                 modify($manager) {finishOperation($operation)};
550             }
551             else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
552                 retract($opTimer);
553                 retract($operation);
554                 modify($manager) {finishOperation($operation)};
555             }
556         }
557
558     } catch (Exception e) {
559         String msg = e.getMessage();
560         logger.warn("{}: {}: operation={}:  AAI failure: {}",
561                     $clName,
562                     $params.getPolicyName() + "." + drools.getRule().getName(),
563                     $operation, msg, e);
564         $operation.setOperationHasException(msg);
565
566         if(request != null) {
567             //
568             // Create a notification for it ("DB Write - end operation")
569             //
570             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
571             notification.setFrom("policy");
572             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
573             notification.setPolicyScope($params.getPolicyScope());
574             notification.setPolicyVersion($params.getPolicyVersion());
575             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
576             notification.setMessage($operation.getOperationHistory());
577             notification.setHistory($operation.getHistory());
578
579             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
580         }
581
582         retract($opTimer);
583         retract($operation);
584         caughtException = true;
585     }
586
587     // Having the modify statement in the catch clause doesn't work for whatever reason
588     if (caughtException) {
589         modify($manager) {finishOperation($operation)};
590     }
591 end
592
593
594 /*
595 *
596 * We were able to acquire a lock so now let's ask Xacml Guard whether
597 * we are allowed to proceed with the request to the actor.
598 *
599 */
600 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
601     when
602         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
603         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
604         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() )
605         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
606         $lock : TargetLock (requestID == $event.getRequestId())
607     then
608
609     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
610     logger.info("{}: {}: event={} manager={} operation={} lock={}",
611                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
612                 $event, $manager, $operation, $lock);
613
614     //
615     // Sending notification that we are about to query Guard ("DB write - start operation")
616     //
617     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
618     notification.setNotification(ControlLoopNotificationType.OPERATION);
619     notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe());
620     notification.setHistory($operation.getHistory());
621     notification.setFrom("policy");
622     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
623     notification.setPolicyScope($params.getPolicyScope());
624     notification.setPolicyVersion($params.getPolicyVersion());
625
626     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
627
628     //
629     // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
630     // just change guardEnabled to false.
631     //
632     // In order to use REST XACML, provide a URL instead of "" as a second argument
633     // to the CallGuardTask() and set the first argument to null
634     // (instead of XacmlPdpEngine).
635     //
636
637     // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
638     boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
639
640     if(guardEnabled){
641
642         Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
643                                                         drools.getWorkingMemory(),
644                                                         $event.getClosedLoopControlName(),
645                                                         $operation.policy.getActor().toString(),
646                                                         $operation.policy.getRecipe(),
647                                                         $operation.getTargetEntity(),
648                                                         $event.getRequestId().toString(),
649                                                         () -> {
650                                                             AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
651                                                             return(resp == null ? null : resp.countVfModules());
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 "GUARD.RESPONSE"
666     when
667         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
668         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 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                  $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
696     notification.setPolicyScope($params.getPolicyScope());
697     notification.setPolicyVersion($params.getPolicyVersion());
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 "APPC.RESPONSE"
730     when
731         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
732         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
742     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
743                  $clName, $params.getPolicyName() + "." + 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                     $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
759         notification.setPolicyScope($params.getPolicyScope());
760         notification.setPolicyVersion($params.getPolicyVersion());
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 "APPC.RESPONSE.CLEANUP"
821     when
822         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
829     logger.debug("{}: {}: orphan appc response={}",
830                 $clName, $params.getPolicyName() + "." + 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 "APPC.LCM.RESPONSE"
844     when
845         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
846         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
856     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
857                 $clName, $params.getPolicyName() + "." + 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                   $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
875       notification.setPolicyScope($params.getPolicyScope());
876       notification.setPolicyVersion($params.getPolicyVersion());
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 "APPC.LCM.RESPONSE.CLEANUP"
927     when
928         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
935     logger.debug("{}: {}: orphan appc response={}",
936                 $clName, $params.getPolicyName() + "." + 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 "SO.RESPONSE"
949     when
950         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
951         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
961     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
962                 $clName, $params.getPolicyName() + "." + 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                     $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
979         notification.setPolicyScope($params.getPolicyScope());
980         notification.setPolicyVersion($params.getPolicyVersion());
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 "VFC.RESPONSE"
1033     when
1034         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1035         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1044         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1045                     $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
1058             notification.setPolicyScope($params.getPolicyScope());
1059             notification.setPolicyVersion($params.getPolicyVersion());
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 "EVENT.MANAGER.OPERATION.TIMEOUT"
1105     timer (expr: $to )
1106     when
1107         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1108         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
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("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1117     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1118                 $clName, $params.getPolicyName() + "." + 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($params.getPolicyName() + "." + drools.getRule().getName());
1131     notification.setPolicyScope($params.getPolicyScope());
1132     notification.setPolicyVersion($params.getPolicyVersion());
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 "EVENT.MANAGER.TIMEOUT"
1170     timer (expr: $to )
1171     when
1172         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1173         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1174         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId() )
1175         $clTimer : ControlLoopTimer ( closedLoopControlName == $event.getClosedLoopControlName(), requestID == $event.getRequestId().toString(), $to : getDelay() )
1176     then
1177
1178     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1179     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1180
1181     logger.debug("{}: {}: event={}",
1182               $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1183               $event);
1184     //
1185     // Tell the Event Manager it has timed out
1186     //
1187     VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1188     if (notification != null) {
1189         notification.setFrom("policy");
1190         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1191         notification.setPolicyScope($params.getPolicyScope());
1192         notification.setPolicyVersion($params.getPolicyVersion());
1193         //
1194         // Let interested parties know
1195         //
1196         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1197     }
1198     //
1199     // Retract the event
1200     //
1201     retract($event);
1202 end
1203
1204 /*
1205 *
1206 * This rule cleans up the manager and other objects after an event has
1207 * been retracted.
1208 *
1209 */
1210 rule "EVENT.MANAGER.CLEANUP"
1211     when
1212         $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestID() )
1213         $clTimer : ControlLoopTimer ( closedLoopControlName == $clName, requestID == $requestId.toString() )
1214         $operations : LinkedList()
1215                         from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName, onset.getRequestId() == $requestId ) )
1216         $opTimers : LinkedList()
1217                         from collect( OperationTimer( closedLoopControlName == $clName, requestID == $requestId.toString() ) )
1218         $locks : LinkedList()
1219                         from collect( TargetLock (requestID == $requestId) )
1220         not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1221     then
1222
1223     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1224     logger.info("{}: {}", $clName, drools.getRule().getName());
1225
1226     logger.debug("{}: {}: manager={} clTimer={} operations={}",
1227               $clName, drools.getRule().getName(),
1228               $manager, $clTimer, $operations.size());
1229
1230     //
1231     // Retract EVERYTHING
1232     //
1233     retract($manager);
1234     retract($clTimer);
1235
1236     for(Object manager: $operations) {
1237         retract((ControlLoopOperationManager) manager);
1238     }
1239     for(Object opTimer: $opTimers) {
1240         retract((OperationTimer) opTimer);
1241     }
1242     for(Object lock: $locks) {
1243         TargetLock tgt = (TargetLock) lock;
1244         //
1245         // Ensure we release the lock
1246         //
1247         PolicyGuard.unlockTarget(tgt);
1248         retract(tgt);
1249     }
1250 end
1251
1252 /*
1253 *
1254 * This rule will clean up any rogue onsets where there is no
1255 * ControlLoopParams object corresponding to the onset event.
1256 *
1257 */
1258 rule "EVENT.CLEANUP"
1259     when
1260         $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1261         not ( ControlLoopParams( getClosedLoopControlName() == $clName) )
1262     then
1263
1264     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1265     logger.info("{}: {}", $clName, drools.getRule().getName());
1266     logger.debug("{}: {}: orphan onset event={}",
1267                 $clName, drools.getRule().getName(), $event);
1268
1269     retract($event);
1270 end