37d7b69361dc09d5391b0b3d9380ff7fa144e581
[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.PolicyEngineConstants;
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             PolicyEngineConstants.getManager().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                 PolicyEngineConstants.getManager().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                 PolicyEngineConstants.getManager().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         PolicyEngineConstants.getManager().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                 PolicyEngineConstants.getManager().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                   PolicyEngineConstants.getManager().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                   Integer timeout = operation.getOperationTimeout();
444                   opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
445                   insert(opTimer);
446
447                   //
448                   // Insert lock into memory
449                   //
450                   insert(result.getB());
451               }
452               else {
453                   logger.debug("The target resource {} is already processing",
454                                 $event.getAai().get($event.getTarget()));
455                   notification = new VirtualControlLoopNotification($event);
456                   notification.setNotification(ControlLoopNotificationType.REJECTED);
457                   notification.setMessage("The target " + $event.getAai().get($event.getTarget()) 
458                       + " is already locked");
459                   notification.setFrom("policy");
460                   notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
461                   notification.setPolicyScope($params.getPolicyScope());
462                   notification.setPolicyVersion($params.getPolicyVersion());
463
464                   PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
465
466                   retract($event);
467                 
468                   // don't retract manager, etc. - a clean-up rule will do that
469
470                 if(result.getB() != null) {
471                   retract(result.getB());
472                 }
473               }
474               logger.info("{}: {}: starting operation={}",
475                           $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
476                           operation);
477             } else {
478               //
479               // Probably waiting for abatement
480               //
481               logger.info("{}: {}: no operation, probably waiting for abatement",
482                           $clName, $params.getPolicyName() + "." + drools.getRule().getName());
483             }
484         }
485     } catch (Exception e) {
486         logger.warn("{}: {}: unexpected",
487                    $clName,
488                    $params.getPolicyName() + "." + drools.getRule().getName(), e);
489
490         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
491         notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
492         notification.setMessage(e.getMessage());
493         notification.setFrom("policy");
494         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
495         notification.setPolicyScope($params.getPolicyScope());
496         notification.setPolicyVersion($params.getPolicyVersion());
497
498         PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
499
500         retract($event);
501                 
502         // don't retract manager, etc. - a clean-up rule will do that
503     }
504
505 end
506
507 /*
508 *
509 * Guard Permitted, let's send request to the actor.
510 *
511 */
512 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
513     when
514         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
515         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
516         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
517             requestId == $event.getRequestId() )
518         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
519             onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
520         $lock : TargetLock (requestId == $event.getRequestId())
521         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
522             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
523     then
524
525     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
526     logger.info("{}: {}: event={} manager={} operation={} lock={}",
527                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
528                 $event, $manager, $operation, $lock);
529
530     Object request = null;
531     boolean caughtException = false;
532
533     try {
534         request = $operation.startOperation($event);
535
536         if (request != null) {
537           logger.debug("{}: {}: starting operation ..",
538                        $clName,
539                        $params.getPolicyName() + "." + drools.getRule().getName());
540           //
541           // Tell interested parties we are performing this Operation
542           //
543           VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
544           notification.setNotification(ControlLoopNotificationType.OPERATION);
545           notification.setMessage($operation.getOperationMessage());
546           notification.setHistory($operation.getHistory());
547           notification.setFrom("policy");
548           notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
549           notification.setPolicyScope($params.getPolicyScope());
550           notification.setPolicyVersion($params.getPolicyVersion());
551
552           PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
553
554           switch ($operation.policy.getActor()){
555
556               case "APPC":
557
558                   if (request instanceof Request) {
559                       PolicyEngineConstants.getManager().deliver("APPC-CL", request);
560                   }
561                   else if (request instanceof LcmRequestWrapper) {
562                       PolicyEngineConstants.getManager().deliver("APPC-LCM-READ", request);
563                   }
564                   break;
565               case "SO":
566                   // at this point the AAI named query request should have already been made, the response 
567                   // recieved and used in the construction of the SO Request which is stored in operationRequest
568
569                   if(request instanceof SoRequest) {
570                       // Call SO. The response will be inserted into memory once it's received
571                       class mySoCallback implements SoManager.SoCallback {
572                           public void onSoResponseWrapper(SoResponseWrapper wrapper) {
573                               drools.getWorkingMemory().insert(wrapper);
574                           }
575                       }
576                       SoActorServiceProvider.sendRequest($event.getRequestId().toString(), 
577                           new mySoCallback(), 
578                           request,
579                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
580                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
581                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.password"));
582                   }
583                   break;
584               case "VFC":
585                   if (request instanceof VfcRequest) {
586                       class myVfcCallback implements VfcManager.VfcCallback {
587                           
588                           public void onResponse(VfcResponse responseError) {
589                               drools.getWorkingMemory().insert(responseError);
590                           }
591                       };
592                       // Start VFC thread
593                       Thread t = new Thread(new VfcManager(new myVfcCallback(),
594                           (VfcRequest)request,
595                           PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.url"),
596                           PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
597                           PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password")));
598                       t.start();
599                   }
600                   break;
601               case "SDNR":
602                   if (request instanceof PciRequestWrapper) {
603                       PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
604                   }
605                   break;
606               
607               case "SDNC":
608                   if (request instanceof SdncRequest) {
609                       class mySdncCallback implements SdncManager.SdncCallback {
610                           public void onCallback(SdncResponse response) {
611                               drools.getWorkingMemory().insert(response);
612                           }
613                       }  
614                       // Start SDNC thread
615                       Thread t = new Thread(new SdncManager(new mySdncCallback(), 
616                           (SdncRequest)request,
617                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
618                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
619                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
620                       t.start();
621                   }
622                   break;                 
623           }
624         } else {
625           //
626           // What happens if its null?
627           //
628             logger.warn("{}: {}: unexpected null operation request",
629                       $clName,
630                       $params.getPolicyName() + "." + drools.getRule().getName());
631             if ("SO".equals($operation.policy.getActor())) {
632                 retract($opTimer);
633                 retract($operation);
634                 modify($manager) {finishOperation($operation)};
635             }
636             else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
637                 retract($opTimer);
638                 retract($operation);
639                 modify($manager) {finishOperation($operation)};
640             }
641             else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
642                 retract($opTimer);
643                 retract($operation);
644                 modify($manager) {finishOperation($operation)};
645             }
646         }
647
648     } catch (Exception e) {
649         String msg = e.getMessage();
650         logger.warn("{}: {}: operation={}:  AAI failure: {}",
651                     $clName,
652                     $params.getPolicyName() + "." + drools.getRule().getName(),
653                     $operation, msg, e);
654         $operation.setOperationHasException(msg);
655
656         if(request != null) {
657             //
658             // Create a notification for it ("DB Write - end operation")
659             //
660             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
661             notification.setFrom("policy");
662             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
663             notification.setPolicyScope($params.getPolicyScope());
664             notification.setPolicyVersion($params.getPolicyVersion());
665             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
666             notification.setMessage($operation.getOperationHistory());
667             notification.setHistory($operation.getHistory());
668
669             PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
670         }
671
672         retract($opTimer);
673         retract($operation);
674         caughtException = true;
675     }
676
677     // Having the modify statement in the catch clause doesn't work for whatever reason
678     if (caughtException) {
679         modify($manager) {finishOperation($operation)};
680     }
681 end
682
683
684 /*
685 *
686 * We were able to acquire a lock so now let's ask Xacml Guard whether
687 * we are allowed to proceed with the request to the actor.
688 *
689 */
690 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
691     when
692         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
693         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
694         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
695             requestId == $event.getRequestId() )
696         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
697             onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
698         $lock : TargetLock (requestId == $event.getRequestId())
699     then
700
701     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
702     logger.info("{}: {}: event={} manager={} operation={} lock={}",
703                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
704                 $event, $manager, $operation, $lock);
705
706     //
707     // Sending notification that we are about to query Guard ("DB write - start operation")
708     //
709     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
710     notification.setNotification(ControlLoopNotificationType.OPERATION);
711     notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " " 
712         + $operation.policy.getRecipe());
713     notification.setHistory($operation.getHistory());
714     notification.setFrom("policy");
715     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
716     notification.setPolicyScope($params.getPolicyScope());
717     notification.setPolicyVersion($params.getPolicyVersion());
718
719     PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
720
721     //
722     // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
723     // just change guardEnabled to false.
724     //
725     // In order to use REST XACML, provide a URL instead of "" as a second argument
726     // to the CallGuardTask() and set the first argument to null
727     // (instead of XacmlPdpEngine).
728     //
729
730     // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
731     boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("guard.disabled"));
732
733     if(guardEnabled){
734
735         Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
736                                                         drools.getWorkingMemory(),
737                                                         $event.getClosedLoopControlName(),
738                                                         $operation.policy.getActor().toString(),
739                                                         $operation.policy.getRecipe(),
740                                                         $operation.getTargetEntity(),
741                                                         $event.getRequestId().toString(),
742                                                         () -> {
743                                                             AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
744                                                             return(resp == null ? null : resp.countVfModules());
745                                                         }));
746         t.start();
747     }
748     else{
749         insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
750     }
751
752 end
753
754 //
755 // This rule will be triggered when a thread talking to the XACML Guard inserts a
756 // guardResponse object into the working memory
757 //
758 rule "GUARD.RESPONSE"
759     when
760         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
761         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
762             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
763         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
764             requestId == $event.getRequestId() )
765         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
766             onset.getRequestId() == $event.getRequestId() )
767         $lock : TargetLock (requestId == $event.getRequestId())
768         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
769             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
770         $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
771     then
772
773     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
774     logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
775                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
776                  $event, $manager, $operation, $lock, $opTimer, $guardResponse);
777
778
779     //we will permit the operation if there was no Guard for it
780     if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
781         $guardResponse.setResult("Permit");
782     }
783
784     //
785     // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
786     //
787     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
788     notification.setNotification(ControlLoopNotificationType.OPERATION);
789     notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
790         + " is " + $guardResponse.getResult());
791     notification.setHistory($operation.getHistory());
792     notification.setFrom("policy");
793     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
794     notification.setPolicyScope($params.getPolicyScope());
795     notification.setPolicyVersion($params.getPolicyVersion());
796
797     PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
798
799     if("Permit".equalsIgnoreCase($guardResponse.getResult())){
800
801         modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
802     }
803     else {
804         //This is the Deny case
805         $operation.startOperation($event);
806         $operation.setOperationHasGuardDeny();
807         retract($opTimer);
808         retract($operation);
809         modify($manager) {finishOperation($operation)};
810     }
811
812     retract($guardResponse);
813
814 end
815
816 /*
817 *
818 * This rule responds to APPC Response Events
819 *
820 * I would have like to be consistent and write the Response like this:
821 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
822 *
823 * However, no compile error was given. But a runtime error was given. I think
824 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
825 *
826 */
827 rule "APPC.RESPONSE"
828     when
829         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
830         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
831             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
832         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
833             requestId == $event.getRequestId() )
834         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
835             onset.getRequestId() == $event.getRequestId() )
836         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
837             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
838         $lock : TargetLock (requestId == $event.getRequestId())
839         $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
840     then
841
842     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
843     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
844     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
845                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
846                  $event, $manager, $operation, $lock, $opTimer, $response);
847     //
848     // Get the result of the operation
849     //
850     PolicyResult policyResult = $operation.onResponse($response);
851     if (policyResult != null) {
852         logger.debug("{}: {}: operation finished - result={}",
853                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
854                     policyResult);
855         //
856         // This Operation has completed, construct a notification showing our results. (DB write - end operation)
857         //
858         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
859         notification.setFrom("policy");
860         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
861         notification.setPolicyScope($params.getPolicyScope());
862         notification.setPolicyVersion($params.getPolicyVersion());
863         notification.setMessage($operation.getOperationHistory());
864         notification.setHistory($operation.getHistory());
865         if (policyResult.equals(PolicyResult.SUCCESS)) {
866             notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
867             //
868             // Let interested parties know
869             //
870             PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
871         } else {
872             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
873             //
874             // Let interested parties know
875             //
876             PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
877         }
878         //
879         // Ensure the operation is complete
880         //
881         if ($operation.isOperationComplete() == true) {
882             //
883             // It is complete, remove it from memory
884             //
885             retract($operation);
886             //
887             // We must also retract the timer object
888             // NOTE: We could write a Rule to do this
889             //
890             retract($opTimer);
891             //
892             // Complete the operation
893             //
894             modify($manager) {finishOperation($operation)};
895         } else {
896             //
897             // Just doing this will kick off the LOCKED rule again
898             //
899             modify($operation) {};
900         }
901     } else {
902         //
903         // Its not finished yet (i.e. expecting more Response objects)
904         //
905         // Or possibly it is a leftover response that we timed the request out previously
906         //
907     }
908     //
909     // We are going to retract these objects from memory
910     //
911     retract($response);
912 end
913
914 /*
915 *
916 * The problem with Responses is that they don't have a controlLoopControlName
917 * field in them, so the only way to attach them is via RequestId. If we have multiple
918 * control loop .drl's loaded in the same container, we need to be sure the cleanup
919 * rules don't remove Responses for other control loops.
920 *
921 */
922 rule "APPC.RESPONSE.CLEANUP"
923     when
924         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
925         $response : Response($id : getCommonHeader().RequestId )
926         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
927     then
928
929     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
930     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
931     logger.debug("{}: {}: orphan appc response={}",
932                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
933
934     //
935     // Retract it
936     //
937     retract($response);
938 end
939
940 /*
941 *
942 * This rule responds to APPC Response Events using the new LCM interface provided by appc
943 *
944 */
945 rule "APPC.LCM.RESPONSE"
946     when
947         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
948         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
949             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
950         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
951             requestId == $event.getRequestId() )
952         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
953             onset.getRequestId() == $event.getRequestId() )
954         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
955             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
956         $lock : TargetLock (requestId == $event.getRequestId())
957         $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
958     then
959
960     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
961     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
962     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
963                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
964                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
965
966     //
967     // Get the result of the operation
968     //
969     PolicyResult policyResult = $operation.onResponse($response);
970     if (policyResult != null) {
971       logger.debug("{}: {}: operation finished - result={}",
972                   $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
973                   policyResult);
974
975       //
976       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
977       //
978       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
979       notification.setFrom("policy");
980       notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
981       notification.setPolicyScope($params.getPolicyScope());
982       notification.setPolicyVersion($params.getPolicyVersion());
983       notification.setMessage($operation.getOperationHistory());
984       notification.setHistory($operation.getHistory());
985       if (policyResult.equals(PolicyResult.SUCCESS)) {
986           notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
987       } else {
988           notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
989       }
990       PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
991       //
992       // Ensure the operation is complete
993       //
994       if ($operation.isOperationComplete() == true) {
995           //
996           // It is complete, remove it from memory
997           //
998           retract($operation);
999           //
1000           // We must also retract the timer object
1001           // NOTE: We could write a Rule to do this
1002           //
1003           retract($opTimer);
1004           //
1005           // Complete the operation
1006           //
1007           modify($manager) {finishOperation($operation)};
1008       } else {
1009           //
1010           // Just doing this will kick off the LOCKED rule again
1011           //
1012           modify($operation) {};
1013       }
1014     } else {
1015         //
1016         // Its not finished yet (i.e. expecting more Response objects)
1017         //
1018         // Or possibly it is a leftover response that we timed the request out previously
1019         //
1020     }
1021     //
1022     // We are going to retract these objects from memory
1023     //
1024     retract($response);
1025 end
1026
1027 /*
1028 *
1029 * Clean Up any lingering LCM reponses
1030 *
1031 */
1032 rule "APPC.LCM.RESPONSE.CLEANUP"
1033     when
1034         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1035         $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1036         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1037     then
1038
1039     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1040     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1041     logger.debug("{}: {}: orphan appc response={}",
1042                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
1043     //
1044     // Retract it
1045     //
1046     retract($response);
1047 end
1048
1049 /*
1050 *
1051 * This rule responds to SO Response Events
1052 *
1053 */
1054 rule "SO.RESPONSE"
1055     when
1056         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1057         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1058             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1059         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1060             requestId == $event.getRequestId() )
1061         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1062             onset.getRequestId() == $event.getRequestId() )
1063         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1064             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1065         $lock : TargetLock (requestId == $event.getRequestId())
1066         $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
1067     then
1068
1069     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1070     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1071     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1072                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1073                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1074
1075     // Get the result of the operation
1076     //
1077     PolicyResult policyResult = $operation.onResponse($response);
1078     if (policyResult != null) {
1079         logger.debug("{}: {}: operation finished - result={}",
1080                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1081                     policyResult);
1082
1083         //
1084         // This Operation has completed, construct a notification showing our results
1085         //
1086         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1087         notification.setFrom("policy");
1088         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1089         notification.setPolicyScope($params.getPolicyScope());
1090         notification.setPolicyVersion($params.getPolicyVersion());
1091         notification.setMessage($operation.getOperationHistory());
1092         notification.setHistory($operation.getHistory());
1093         if (policyResult.equals(PolicyResult.SUCCESS)) {
1094             notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1095         } else {
1096             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1097
1098         }
1099         PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1100         //
1101         // Ensure the operation is complete
1102         //
1103         if ($operation.isOperationComplete() == true) {
1104             //
1105             // It is complete, remove it from memory
1106             //
1107             retract($operation);
1108             //
1109             // We must also retract the timer object
1110             // NOTE: We could write a Rule to do this
1111             //
1112             retract($opTimer);
1113             //
1114             // Complete the operation
1115             //
1116             modify($manager) {finishOperation($operation)};
1117         } else {
1118             //
1119             // Just doing this will kick off the LOCKED rule again
1120             //
1121             modify($operation) {};
1122         }
1123     } else {
1124         //
1125         // Its not finished yet (i.e. expecting more Response objects)
1126         //
1127         // Or possibly it is a leftover response that we timed the request out previously
1128         //
1129     }
1130     //
1131     // We are going to retract these objects from memory
1132     //
1133     retract($response);
1134
1135 end
1136
1137 /*
1138 *
1139 * This rule responds to VFC Response Events
1140 *
1141 */
1142 rule "VFC.RESPONSE"
1143     when
1144         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1145         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1146             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1147         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1148             requestId == $event.getRequestId() )
1149         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1150             onset.getRequestId() == $event.getRequestId() )
1151         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1152             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1153         $lock : TargetLock (requestId == $event.getRequestId())
1154         $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1155     then
1156         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1157         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1158         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1159                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1160                     $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1161
1162         // Get the result of the operation
1163         //
1164         PolicyResult policyResult = $operation.onResponse($response);
1165         if (policyResult != null) {
1166             //
1167             // This Operation has completed, construct a notification showing our results
1168             //
1169             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1170             notification.setFrom("policy");
1171             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1172             notification.setPolicyScope($params.getPolicyScope());
1173             notification.setPolicyVersion($params.getPolicyVersion());
1174             notification.setMessage($operation.getOperationHistory());
1175             notification.setHistory($operation.getHistory());
1176             //
1177             // Ensure the operation is complete
1178             //
1179             if ($operation.isOperationComplete() == true) {
1180                 //
1181                 // It is complete, remove it from memory
1182                 //
1183                 retract($operation);
1184                 //
1185                 // We must also retract the timer object
1186                 // NOTE: We could write a Rule to do this
1187                 //
1188                 retract($opTimer);
1189                 //
1190                 // Complete the operation
1191                 //
1192                 modify($manager) {finishOperation($operation)};
1193             } else {
1194                 //
1195                 // Just doing this will kick off the LOCKED rule again
1196                 //
1197                 modify($operation) {};
1198             }
1199         } else {
1200             //
1201             // Its not finished yet (i.e. expecting more Response objects)
1202             //
1203             // Or possibly it is a leftover response that we timed the request out previously
1204             //
1205         }
1206         //
1207         // We are going to retract these objects from memory
1208         //
1209         retract($response);
1210
1211 end
1212
1213 /*
1214 *
1215 * This rule responds to SDNC Response Events
1216 *
1217 */
1218 rule "SDNC.RESPONSE"
1219     when
1220         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1221         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1222         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestId == $event.getRequestId() )
1223         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId() )
1224         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1225             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1226         $lock : TargetLock (requestId == $event.getRequestId())
1227         $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1228     then
1229         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1230         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1231         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1232                         $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1233                         $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1234
1235         // Get the result of the operation
1236         //
1237         PolicyResult policyResult = $operation.onResponse($response);
1238         if (policyResult != null) {
1239             //
1240             // This Operation has completed, construct a notification showing our results
1241             //
1242             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1243             notification.setFrom("policy");
1244             notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1245             notification.setPolicyScope($params.getPolicyScope());
1246             notification.setPolicyVersion($params.getPolicyVersion());
1247             notification.setMessage($operation.getOperationHistory());
1248             notification.setHistory($operation.getHistory());
1249             //
1250             // Ensure the operation is complete
1251             //
1252             if ($operation.isOperationComplete()) {
1253                 //
1254                 // It is complete, remove it from memory
1255                 //
1256                 retract($operation);
1257                 //
1258                 // We must also retract the timer object
1259                 // NOTE: We could write a Rule to do this
1260                 //
1261                 retract($opTimer);
1262                 //
1263                 // Complete the operation
1264                 //
1265                 modify($manager) {finishOperation($operation)};
1266             } else {
1267                 //
1268                 // Just doing this will kick off the LOCKED rule again
1269                 //
1270                 modify($operation) {};
1271             }
1272         } else {
1273             //
1274             // Its not finished yet (i.e. expecting more Response objects)
1275             //
1276             // Or possibly it is a leftover response that we timed the request out previously
1277             //
1278         }
1279         //
1280         // We are going to retract these objects from memory
1281         //
1282         retract($response);
1283
1284 end
1285
1286 /*
1287 *
1288 * This manages a single timer.
1289 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1290 *
1291 */
1292 rule "TIMER.FIRED"
1293     timer (expr: $timeout)
1294     when
1295         $timer : ControlLoopTimer($timeout : delay, !expired)
1296     then
1297         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1298         logger.info("This is TIMER.FIRED");
1299         modify($timer){setExpired(true)};
1300     end
1301
1302 /*
1303 *
1304 * This is the timer that manages the timeout for an individual operation.
1305 *
1306 */
1307 rule "EVENT.MANAGER.OPERATION.TIMEOUT"
1308     when
1309         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1310         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1311         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1312             requestId == $event.getRequestId() )
1313         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1314             onset.getRequestId() == $event.getRequestId() )
1315         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1316             requestId == $event.getRequestId().toString(), timerType == "Operation", expired )
1317         $lock : TargetLock (requestId == $event.getRequestId())
1318     then
1319
1320     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1321     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1322     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1323                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1324                 $event, $manager, $operation, $lock, $operation, $opTimer);
1325
1326     //
1327     // Tell it its timed out
1328     //
1329     $operation.setOperationHasTimedOut();
1330     //
1331     // Create a notification for it ("DB Write - end operation")
1332     //
1333     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1334     notification.setFrom("policy");
1335     notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1336     notification.setPolicyScope($params.getPolicyScope());
1337     notification.setPolicyVersion($params.getPolicyVersion());
1338     notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1339     notification.setMessage($operation.getOperationHistory());
1340     notification.setHistory($operation.getHistory());
1341     //
1342     // Let interested parties know
1343     //
1344     PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1345     //
1346     // Get rid of the timer
1347     //
1348     retract($opTimer);
1349     //
1350     // Ensure the operation is complete
1351     //
1352     if ($operation.isOperationComplete() == true) {
1353         //
1354         // It is complete, remove it from memory
1355         //
1356         retract($operation);
1357         //
1358         // Complete the operation
1359         //
1360         modify($manager) {finishOperation($operation)};
1361     } else {
1362         //
1363         // Just doing this will kick off the LOCKED rule again
1364         //
1365         modify($operation) {};
1366     }
1367 end
1368
1369 /*
1370 *
1371 * This is the timer that manages the overall control loop timeout.
1372 *
1373 */
1374 rule "EVENT.MANAGER.TIMEOUT"
1375     when
1376         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1377         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1378         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1379             requestId == $event.getRequestId() )
1380         $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1381             requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", expired )
1382     then
1383
1384     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1385     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1386
1387     logger.debug("{}: {}: event={}",
1388               $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1389               $event);
1390     //
1391     // Tell the Event Manager it has timed out
1392     //
1393     VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1394     if (notification != null) {
1395         notification.setFrom("policy");
1396         notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1397         notification.setPolicyScope($params.getPolicyScope());
1398         notification.setPolicyVersion($params.getPolicyVersion());
1399         //
1400         // Let interested parties know
1401         //
1402         PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1403     }
1404     //
1405     // Retract the event
1406     //
1407     retract($event);
1408 end
1409
1410 /*
1411 *
1412 * This rule cleans up the manager and other objects after an event has
1413 * been retracted.
1414 *
1415 */
1416 rule "EVENT.MANAGER.CLEANUP"
1417     when
1418         $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
1419         $operations : LinkedList()
1420                         from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName, 
1421                             onset.getRequestId() == $requestId ) )
1422         $timers : LinkedList()
1423                         from collect( ControlLoopTimer( closedLoopControlName == $clName, 
1424                             requestId == $requestId.toString() ) )
1425         $locks : LinkedList()
1426                         from collect( TargetLock (requestId == $requestId) )
1427         not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1428     then
1429
1430     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1431     logger.info("{}: {}", $clName, drools.getRule().getName());
1432
1433     logger.debug("{}: {}: manager={} timers={} operations={}",
1434               $clName, drools.getRule().getName(),
1435               $manager, $timers.size(), $operations.size());
1436
1437     //
1438     // Retract EVERYTHING
1439     //
1440     retract($manager);
1441
1442     for(Object manager: $operations) {
1443         retract((ControlLoopOperationManager) manager);
1444     }
1445     for(Object timer: $timers) {
1446         retract((ControlLoopTimer) timer);
1447     }
1448     for(Object lock: $locks) {
1449         TargetLock tgt = (TargetLock) lock;
1450         //
1451         // Ensure we release the lock
1452         //
1453         PolicyGuard.unlockTarget(tgt);
1454         retract(tgt);
1455     }
1456 end
1457
1458 /*
1459 *
1460 * This rule will clean up any rogue onsets where there is no
1461 * ControlLoopParams object corresponding to the onset event.
1462 *
1463 */
1464 rule "EVENT.CLEANUP"
1465     when
1466         $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1467         not ( ControlLoopParams( getClosedLoopControlName() == $clName) )
1468     then
1469
1470     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1471     logger.info("{}: {}", $clName, drools.getRule().getName());
1472     logger.debug("{}: {}: orphan onset event={}",
1473                 $clName, drools.getRule().getName(), $event);
1474
1475     retract($event);
1476 end
1477
1478 /*
1479 *
1480 * This rule responds to SDNR Response Events.
1481 *
1482 */
1483 rule "SDNR.RESPONSE"
1484     when
1485         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1486         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
1487             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1488         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
1489             requestId == $event.getRequestId() )
1490         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
1491             onset.getRequestId() == $event.getRequestId() )
1492         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
1493             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1494         $lock : TargetLock (requestId == $event.getRequestId())
1495         $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1496     then
1497
1498     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1499     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1500     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1501                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1502                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1503
1504     //
1505     // Get the result of the operation
1506     //
1507     PolicyResult policyResult = $operation.onResponse($response);
1508     if (policyResult != null) {
1509       logger.debug("{}: {}: operation finished - result={}",
1510                   $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1511                   policyResult);
1512
1513       //
1514       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1515       //
1516       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1517       notification.setFrom("policy");
1518       notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1519       notification.setPolicyScope($params.getPolicyScope());
1520       notification.setPolicyVersion($params.getPolicyVersion());
1521       notification.setMessage($operation.getOperationHistory());
1522       notification.setHistory($operation.getHistory());
1523       if (policyResult.equals(PolicyResult.SUCCESS)) {
1524           notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1525       } else {
1526           notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1527       }
1528       PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1529
1530       ControlLoopResponse clResponse = $operation.getControlLoopResponse($response, $event);
1531       PolicyEngineConstants.getManager().deliver("DCAE_CL_RSP", clResponse);
1532       //
1533       // Ensure the operation is complete
1534       //
1535       if ($operation.isOperationComplete() == true) {
1536           //
1537           // It is complete, remove it from memory
1538           //
1539           retract($operation);
1540           //
1541           // We must also retract the timer object
1542           // NOTE: We could write a Rule to do this
1543           //
1544           retract($opTimer);
1545           //
1546           // Complete the operation
1547           //
1548           modify($manager) {finishOperation($operation)};
1549       } else {
1550           //
1551           // Just doing this will kick off the LOCKED rule again
1552           //
1553           modify($operation) {};
1554       }
1555     } else {
1556         //
1557         // Its not finished yet (i.e. expecting more Response objects)
1558         //
1559         // Or possibly it is a leftover response that we timed the request out previously
1560         //
1561     }
1562     //
1563     // We are going to retract these objects from memory
1564     //
1565     retract($response);
1566 end
1567
1568 /*
1569 *
1570 * Clean Up any lingering SDNR reponses.
1571 *
1572 */
1573 rule "SDNR.RESPONSE.CLEANUP"
1574     when
1575         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1576         $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1577         not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1578     then
1579
1580     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1581     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1582     logger.debug("{}: {}: orphan sdnr response={}",
1583                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
1584     //
1585     // Retract it
1586     //
1587     retract($response);
1588 end