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