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