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