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