2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.controlloop;
23 import org.onap.policy.controlloop.VirtualControlLoopEvent;
24 import org.onap.policy.controlloop.VirtualControlLoopNotification;
25 import org.onap.policy.controlloop.ControlLoopEventStatus;
26 import org.onap.policy.controlloop.ControlLoopNotificationType;
27 import org.onap.policy.controlloop.ControlLoopLogger;
28 import org.onap.policy.controlloop.policy.PolicyResult;
29 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
30 import org.onap.policy.controlloop.policy.Policy;
31 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
32 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS;
33 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
34 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
35 import org.onap.policy.aai.AaiNqResponseWrapper;
36 import org.onap.policy.appc.Request;
37 import org.onap.policy.appc.Response;
38 import org.onap.policy.appc.CommonHeader;
39 import org.onap.policy.appclcm.LcmRequestWrapper;
40 import org.onap.policy.appclcm.LcmResponseWrapper;
41 import org.onap.policy.appclcm.LcmRequest;
42 import org.onap.policy.appclcm.LcmResponse;
43 import org.onap.policy.appclcm.LcmCommonHeader;
44 import org.onap.policy.vfc.VFCRequest;
45 import org.onap.policy.vfc.VFCResponse;
46 import org.onap.policy.vfc.VFCManager;
47 import org.onap.policy.so.SOManager;
48 import org.onap.policy.so.SORequest;
49 import org.onap.policy.so.SORequestStatus;
50 import org.onap.policy.so.SORequestDetails;
51 import org.onap.policy.so.SOModelInfo;
52 import org.onap.policy.so.SOCloudConfiguration;
53 import org.onap.policy.so.SORequestInfo;
54 import org.onap.policy.so.SORequestParameters;
55 import org.onap.policy.so.SORelatedInstanceListElement;
56 import org.onap.policy.so.SORelatedInstance;
57 import org.onap.policy.so.SOResponse;
58 import org.onap.policy.so.SOResponseWrapper;
59 import org.onap.policy.sdnc.SdncRequest;
60 import org.onap.policy.sdnc.SdncManager;
61 import org.onap.policy.sdnc.SdncResponse;
62 import org.onap.policy.guard.PolicyGuard;
63 import org.onap.policy.guard.PolicyGuard.LockResult;
64 import org.onap.policy.guard.TargetLock;
65 import org.onap.policy.guard.GuardResult;
66 import org.onap.policy.guard.PolicyGuardRequest;
67 import org.onap.policy.guard.PolicyGuardResponse;
68 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
69 import org.onap.policy.guard.PolicyGuardXacmlHelper;
71 import org.yaml.snakeyaml.Yaml;
72 import org.yaml.snakeyaml.constructor.Constructor;
74 import org.slf4j.LoggerFactory;
75 import org.slf4j.Logger;
77 import java.time.Instant;
78 import java.util.LinkedList;
79 import java.util.Iterator;
81 import org.onap.policy.drools.system.PolicyEngine;
84 * This structure mimics the Params structure.
85 * Its only purpose is to allow management of
86 * rules by the PAP component..
87 * It has no use at runtime since the rules go by
88 * Params for matching purposes.
91 closedLoopControlName : String
92 controlLoopYaml : String
96 * Control Loop Identity
99 closedLoopControlName : String
100 controlLoopYaml : String
104 * Used to clean up Params that no longer have associated rules.
106 declare ParamsCleaner
107 closedLoopControlName : String
108 controlLoopYaml : String
112 * This object is to provide support for timeouts
113 * due to a bug in drools' built-in timers
115 declare ControlLoopTimer
116 closedLoopControlName : String
120 //timerType is the type of timer: either "ClosedLoop" or "Operation"
126 * Called once and only once to insert the parameters into working memory for this Closed Loop policy.
127 * This has a higher salience so we can ensure that the Params is created before we have a chance to
128 * discard any events.
131 rule "${policyName}.SETUP"
134 not( Params( getClosedLoopControlName() == "${closedLoopControlName}",
135 getControlLoopYaml() == "${controlLoopYaml}" ) )
138 Params params = new Params();
139 params.setClosedLoopControlName("${closedLoopControlName}");
140 params.setControlLoopYaml("${controlLoopYaml}");
143 // Note: globals have bad behavior when persistence is used,
144 // hence explicitly getting the logger vs using a global
146 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
147 logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(),
148 params.getControlLoopYaml());
153 * This rule responds to DCAE Events where there is no manager yet. Either it is
154 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
157 rule "${policyName}.EVENT"
159 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
160 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
161 not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
162 requestID == $event.getRequestId() ) )
165 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
166 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
171 // Check the event, because we need it to not be null when
172 // we create the ControlLoopEventManager. The ControlLoopEventManager
173 // will do extra syntax checking as well check if the closed loop is disabled.
175 if ($event.getRequestId() == null) {
176 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
177 notification.setNotification(ControlLoopNotificationType.REJECTED);
178 notification.setFrom("policy");
179 notification.setMessage("Missing requestId");
180 notification.setPolicyName(drools.getRule().getName());
181 notification.setPolicyScope("${policyScope}");
182 notification.setPolicyVersion("${policyVersion}");
185 // Let interested parties know
187 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
190 // Retract it from memory
193 } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
194 throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
197 // Create an EventManager
199 ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(),
200 $event.getRequestId());
202 // Determine if EventManager can actively process the event
203 // (i.e. syntax, is_closed_loop_disabled checks etc.)
205 VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
206 notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
207 notification.setPolicyName(drools.getRule().getName());
208 notification.setPolicyScope("${policyScope}");
209 notification.setPolicyVersion("${policyVersion}");
211 // Are we actively pursuing this event?
213 if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
215 // Insert Event Manager into memory, this will now kick off processing.
219 // Let interested parties know
221 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
223 // Setup the Overall Control Loop timer
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");
236 // Let interested parties know
238 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
240 // Retract it from memory
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.
251 } catch (Exception e) {
252 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
254 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
255 notification.setNotification(ControlLoopNotificationType.REJECTED);
256 notification.setMessage("Exception occurred: " + e.getMessage());
257 notification.setPolicyName(drools.getRule().getName());
258 notification.setPolicyScope("${policyScope}");
259 notification.setPolicyVersion("${policyVersion}");
263 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
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.
277 rule "${policyName}.EVENT.MANAGER"
279 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
280 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
281 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
282 requestID == $event.getRequestId() )
283 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
284 requestID == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
287 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
288 logger.info("{}: {}: event={} manager={} clTimer={}",
289 $params.getClosedLoopControlName(), drools.getRule().getName(),
290 $event, $manager, $clTimer);
294 // Check which event this is.
296 ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event);
298 // Check what kind of event this is
300 if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) {
302 // We don't care about subsequent onsets
304 logger.info("{}: {}: subsequent onset",
305 $params.getClosedLoopControlName(), drools.getRule().getName());
309 if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) {
311 // Ignore any bad syntax events
313 logger.warn("{}: {}: syntax error",
314 $params.getClosedLoopControlName(), drools.getRule().getName());
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.
323 if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) {
324 logger.warn("{}: {}: not first onset",
325 $params.getClosedLoopControlName(), drools.getRule().getName());
329 logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(),
330 drools.getRule().getName(), $event.getTarget());
332 // Now start seeing if we need to process this event
336 // Check if this is a Final Event
338 VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
341 if (notification != null) {
343 // Its final, but are we waiting for abatement?
345 if ($manager.getNumAbatements() > 0) {
346 logger.info("{}: {}: abatement received for {}. Closing the control loop",
347 $params.getClosedLoopControlName(), drools.getRule().getName(),
348 $event.getRequestId());
350 /// DB Write---end event processing for this RequestId()
351 $manager.commitAbatement("Event Abated","Closed");
353 notification.setFrom("policy");
354 notification.setPolicyName(drools.getRule().getName());
355 notification.setPolicyScope("${policyScope}");
356 notification.setPolicyVersion("${policyVersion}");
358 // In this case, we are done
360 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
364 TargetLock lock = $manager.unlockCurrentOperation();
366 logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(),
367 drools.getRule().getName(), lock);
371 // Retract everything from memory
373 logger.info("{}: {}: retracting onset, manager, and timer",
374 $params.getClosedLoopControlName(), drools.getRule().getName());
376 retract($manager.getOnsetEvent());
380 // TODO - what if we get subsequent Events for this RequestId?
381 // By default, it will all start over again. May be confusing for Ruby.
382 // Or, we could track this and then subsequently ignore the events
386 // Check whether we need to wait for abatement
388 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
389 logger.info("{}: {}: waiting for abatement ..",
390 $params.getClosedLoopControlName(), drools.getRule().getName());
392 logger.info("{}: {}: no abatement expect for {}. Closing the control loop",
393 $params.getClosedLoopControlName(), drools.getRule().getName(),
394 $event.getRequestId());
396 notification.setFrom("policy");
397 notification.setPolicyName(drools.getRule().getName());
398 notification.setPolicyScope("${policyScope}");
399 notification.setPolicyVersion("${policyVersion}");
402 // In this case, we are done
404 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
408 TargetLock lock = $manager.unlockCurrentOperation();
410 logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(),
411 drools.getRule().getName(), lock);
415 // Retract everything from memory
417 logger.info("{}: {}: retracting onset, manager, and timer",
418 $params.getClosedLoopControlName(), drools.getRule().getName());
420 retract($manager.getOnsetEvent());
427 // NOT final, so let's ask for the next operation
429 ControlLoopOperationManager operation = $manager.processControlLoop();
430 if (operation != null) {
432 // Let's ask for a lock right away
434 LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
435 logger.info("{}: {}: guard lock acquired={}",
436 $params.getClosedLoopControlName(), drools.getRule().getName(),
438 if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
440 // insert the operation into memory
444 // insert operation timeout object
446 ControlLoopTimer opTimer = new ControlLoopTimer();
447 opTimer.setTimerType("Operation");
448 opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
449 opTimer.setRequestID($event.getRequestId().toString());
450 opTimer.setDelay(operation.getOperationTimeout().toString() + "s");
454 // Insert lock into memory
456 insert(result.getB());
458 logger.debug("The target resource {} is already processing",
459 $event.getAai().get($event.getTarget()));
460 notification = new VirtualControlLoopNotification($event);
461 notification.setNotification(ControlLoopNotificationType.REJECTED);
462 notification.setMessage("The target " + $event.getAai().get($event.getTarget())
463 + " is already locked");
464 notification.setFrom("policy");
465 notification.setPolicyName(drools.getRule().getName());
466 notification.setPolicyScope("${policyScope}");
467 notification.setPolicyVersion("${policyVersion}");
469 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
475 if (result.getB() != null) {
476 retract(result.getB());
479 logger.info("{}: {}: starting operation={}",
480 $params.getClosedLoopControlName(), drools.getRule().getName(),
484 // Probably waiting for abatement
486 logger.info("{}: {}: no operation, probably waiting for abatement",
487 $params.getClosedLoopControlName(), drools.getRule().getName());
490 } catch (Exception e) {
491 logger.warn("{}: {}: unexpected",
492 $params.getClosedLoopControlName(),
493 drools.getRule().getName(), e);
495 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
496 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
497 notification.setMessage(e.getMessage());
498 notification.setFrom("policy");
499 notification.setPolicyName(drools.getRule().getName());
500 notification.setPolicyScope("${policyScope}");
501 notification.setPolicyVersion("${policyVersion}");
503 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
514 * Guard Permitted, let's send request to the actor.
517 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
519 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
520 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
521 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
522 requestID == $event.getRequestId() )
523 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
524 onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
525 $lock : TargetLock (requestID == $event.getRequestId())
526 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
527 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
530 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
531 logger.info("{}: {}: event={} manager={} operation={} lock={}",
532 $params.getClosedLoopControlName(), drools.getRule().getName(),
533 $event, $manager, $operation, $lock);
535 Object request = null;
536 boolean caughtException = false;
539 request = $operation.startOperation($event);
541 if (request != null) {
542 logger.debug("{}: {}: starting operation ..",
543 $params.getClosedLoopControlName(), drools.getRule().getName());
545 // Tell interested parties we are performing this Operation
547 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
548 notification.setNotification(ControlLoopNotificationType.OPERATION);
549 notification.setMessage($operation.getOperationMessage());
550 notification.setHistory($operation.getHistory());
551 notification.setFrom("policy");
552 notification.setPolicyName(drools.getRule().getName());
553 notification.setPolicyScope("${policyScope}");
554 notification.setPolicyVersion("${policyVersion}");
556 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
558 switch ($operation.policy.getActor()){
561 if (request instanceof Request) {
562 PolicyEngine.manager.deliver("APPC-CL", request);
564 else if (request instanceof LcmRequestWrapper) {
565 PolicyEngine.manager.deliver("APPC-LCM-READ", request);
569 // at this point the AAI named query request should have already been made,
570 // the response recieved and used
571 // in the construction of the SO Request which is stored in operationRequest
573 if(request instanceof SORequest) {
574 // Call SO. The response will be inserted into memory once it's received
575 SoActorServiceProvider.sendRequest($event.getRequestId().toString(), drools.getWorkingMemory(),
580 if (request instanceof VFCRequest) {
582 Thread t = new Thread(new VFCManager(drools.getWorkingMemory(), (VFCRequest)request));
588 if (request instanceof SdncRequest) {
590 Thread t = new Thread(new SdncManager(drools.getWorkingMemory(), (SdncRequest)request));
597 // What happens if its null?
599 logger.warn("{}: {}: unexpected null operation request",
600 $params.getClosedLoopControlName(),
601 drools.getRule().getName());
602 if ("SO".equals($operation.policy.getActor())) {
605 modify($manager) {finishOperation($operation)};
607 else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
610 modify($manager) {finishOperation($operation)};
614 } catch (Exception e) {
615 String msg = e.getMessage();
616 logger.warn("{}: {}: operation={}: AAI failure: {}",
617 $params.getClosedLoopControlName(), drools.getRule().getName(),
619 $operation.setOperationHasException(msg);
621 if(request != null) {
623 // Create a notification for it ("DB Write - end operation")
625 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
626 notification.setFrom("policy");
627 notification.setPolicyName(drools.getRule().getName());
628 notification.setPolicyScope("${policyScope}");
629 notification.setPolicyVersion("${policyVersion}");
630 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
631 notification.setMessage($operation.getOperationHistory());
632 notification.setHistory($operation.getHistory());
634 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
639 caughtException = true;
642 // Having the modify statement in the catch clause doesn't work for whatever reason
643 if (caughtException) {
644 modify($manager) {finishOperation($operation)};
651 * We were able to acquire a lock so now let's ask Xacml Guard whether
652 * we are allowed to proceed with the request to the actor.
655 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
657 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
658 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
659 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
660 requestID == $event.getRequestId() )
661 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
662 onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
663 $lock : TargetLock (requestID == $event.getRequestId())
666 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
667 logger.info("{}: {}: event={} manager={} operation={} lock={}",
668 $params.getClosedLoopControlName(), drools.getRule().getName(),
669 $event, $manager, $operation, $lock);
672 // Sending notification that we are about to query Guard ("DB write - start operation")
674 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
675 notification.setNotification(ControlLoopNotificationType.OPERATION);
676 notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
677 + $operation.policy.getRecipe());
678 notification.setHistory($operation.getHistory());
679 notification.setFrom("policy");
680 notification.setPolicyName(drools.getRule().getName());
681 notification.setPolicyScope("${policyScope}");
682 notification.setPolicyVersion("${policyVersion}");
684 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
687 // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
688 // just change guardEnabled to false.
690 // In order to use REST XACML, provide a URL instead of "" as a second argument
691 // to the CallGuardTask() and set the first argument to null
692 // (instead of XacmlPdpEngine).
695 // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
696 boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
700 Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
701 drools.getWorkingMemory(),
702 $event.getClosedLoopControlName(),
703 $operation.policy.getActor().toString(),
704 $operation.policy.getRecipe(),
705 $operation.getTargetEntity(),
706 $event.getRequestId().toString(),
708 AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
709 return(resp == null ? null : resp.countVfModules());
714 insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
720 // This rule will be triggered when a thread talking to the XACML Guard inserts a
721 // guardResponse object into the working memory
723 rule "${policyName}.GUARD.RESPONSE"
725 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
726 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
727 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
728 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
729 requestID == $event.getRequestId() )
730 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
731 onset.getRequestId() == $event.getRequestId() )
732 $lock : TargetLock (requestID == $event.getRequestId())
733 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
734 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
735 $guardResponse : PolicyGuardResponse(requestID == $event.getRequestId(), $operation.policy.recipe == operation)
738 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
739 logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
740 $params.getClosedLoopControlName(), drools.getRule().getName(),
741 $event, $manager, $operation, $lock, $opTimer, $guardResponse);
744 //we will permit the operation if there was no Guard for it
745 if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
746 $guardResponse.setResult("Permit");
750 // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
752 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
753 notification.setNotification(ControlLoopNotificationType.OPERATION);
754 notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
755 + " is " + $guardResponse.getResult());
756 notification.setHistory($operation.getHistory());
757 notification.setFrom("policy");
758 notification.setPolicyName(drools.getRule().getName());
759 notification.setPolicyScope("${policyScope}");
760 notification.setPolicyVersion("${policyVersion}");
762 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
764 if("Permit".equalsIgnoreCase($guardResponse.getResult())){
766 modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
769 //This is the Deny case
770 $operation.startOperation($event);
771 $operation.setOperationHasGuardDeny();
774 modify($manager) {finishOperation($operation)};
777 retract($guardResponse);
783 * This rule responds to APPC Response Events
785 * I would have like to be consistent and write the Response like this:
786 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
788 * However, no compile error was given. But a runtime error was given. I think
789 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
792 rule "${policyName}.APPC.RESPONSE"
794 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
795 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
796 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
797 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
798 requestID == $event.getRequestId() )
799 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
800 onset.getRequestId() == $event.getRequestId() )
801 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
802 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
803 $lock : TargetLock (requestID == $event.getRequestId())
804 $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
807 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
808 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
809 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
810 $params.getClosedLoopControlName(), drools.getRule().getName(),
811 $event, $manager, $operation, $lock, $opTimer, $response);
813 // Get the result of the operation
815 PolicyResult policyResult = $operation.onResponse($response);
816 if (policyResult != null) {
817 logger.debug("{}: {}: operation finished - result={}",
818 $params.getClosedLoopControlName(), drools.getRule().getName(),
821 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
823 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
824 notification.setFrom("policy");
825 notification.setPolicyName(drools.getRule().getName());
826 notification.setPolicyScope("${policyScope}");
827 notification.setPolicyVersion("${policyVersion}");
828 notification.setMessage($operation.getOperationHistory());
829 notification.setHistory($operation.getHistory());
830 if (policyResult.equals(PolicyResult.SUCCESS)) {
831 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
833 // Let interested parties know
835 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
837 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
839 // Let interested parties know
841 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
844 // Ensure the operation is complete
846 if ($operation.isOperationComplete() == true) {
848 // It is complete, remove it from memory
852 // We must also retract the timer object
853 // NOTE: We could write a Rule to do this
857 // Complete the operation
859 modify($manager) {finishOperation($operation)};
862 // Just doing this will kick off the LOCKED rule again
864 modify($operation) {};
868 // Its not finished yet (i.e. expecting more Response objects)
870 // Or possibly it is a leftover response that we timed the request out previously
874 // We are going to retract these objects from memory
881 * The problem with Responses is that they don't have a controlLoopControlName
882 * field in them, so the only way to attach them is via RequestId. If we have multiple
883 * control loop .drl's loaded in the same container, we need to be sure the cleanup
884 * rules don't remove Responses for other control loops.
887 rule "${policyName}.APPC.RESPONSE.CLEANUP"
889 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
890 $response : Response($id : getCommonHeader().RequestId )
891 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
894 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
895 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
896 logger.debug("{}: {}: orphan appc response={}",
897 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
907 * This rule responds to APPC Response Events using the new LCM interface provided by appc
910 rule "${policyName}.APPC.LCM.RESPONSE"
912 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
913 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
914 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
915 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
916 requestID == $event.getRequestId() )
917 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
918 onset.getRequestId() == $event.getRequestId() )
919 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
920 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
921 $lock : TargetLock (requestID == $event.getRequestId())
922 $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
925 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
926 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
927 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
928 $params.getClosedLoopControlName(), drools.getRule().getName(),
929 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
932 // Get the result of the operation
934 PolicyResult policyResult = $operation.onResponse($response);
935 if (policyResult != null) {
936 logger.debug("{}: {}: operation finished - result={}",
937 $params.getClosedLoopControlName(), drools.getRule().getName(),
941 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
943 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
944 notification.setFrom("policy");
945 notification.setPolicyName(drools.getRule().getName());
946 notification.setPolicyScope("${policyScope}");
947 notification.setPolicyVersion("${policyVersion}");
948 notification.setMessage($operation.getOperationHistory());
949 notification.setHistory($operation.getHistory());
950 if (policyResult.equals(PolicyResult.SUCCESS)) {
951 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
953 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
955 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
957 // Ensure the operation is complete
959 if ($operation.isOperationComplete() == true) {
961 // It is complete, remove it from memory
965 // We must also retract the timer object
966 // NOTE: We could write a Rule to do this
970 // Complete the operation
972 modify($manager) {finishOperation($operation)};
975 // Just doing this will kick off the LOCKED rule again
977 modify($operation) {};
981 // Its not finished yet (i.e. expecting more Response objects)
983 // Or possibly it is a leftover response that we timed the request out previously
987 // We are going to retract these objects from memory
994 * Clean Up any lingering LCM reponses
997 rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
999 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1000 $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1001 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1004 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1005 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1006 logger.debug("{}: {}: orphan appc response={}",
1007 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1016 * This rule responds to SO Response Events
1019 rule "${policyName}.SO.RESPONSE"
1021 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1022 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1023 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1024 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1025 requestID == $event.getRequestId() )
1026 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1027 onset.getRequestId() == $event.getRequestId() )
1028 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1029 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1030 $lock : TargetLock (requestID == $event.getRequestId())
1031 $response : SOResponseWrapper(requestID.toString() == $event.getRequestId().toString() )
1034 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1035 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1036 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1037 $params.getClosedLoopControlName(), drools.getRule().getName(),
1038 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1040 // Get the result of the operation
1042 PolicyResult policyResult = $operation.onResponse($response);
1043 if (policyResult != null) {
1044 logger.debug("{}: {}: operation finished - result={}",
1045 $params.getClosedLoopControlName(), drools.getRule().getName(),
1049 // This Operation has completed, construct a notification showing our results
1051 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1052 notification.setFrom("policy");
1053 notification.setPolicyName(drools.getRule().getName());
1054 notification.setPolicyScope("${policyScope}");
1055 notification.setPolicyVersion("${policyVersion}");
1056 notification.setMessage($operation.getOperationHistory());
1057 notification.setHistory($operation.getHistory());
1058 if (policyResult.equals(PolicyResult.SUCCESS)) {
1059 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1061 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1064 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1066 // Ensure the operation is complete
1068 if ($operation.isOperationComplete() == true) {
1070 // It is complete, remove it from memory
1072 retract($operation);
1074 // We must also retract the timer object
1075 // NOTE: We could write a Rule to do this
1079 // Complete the operation
1081 modify($manager) {finishOperation($operation)};
1084 // Just doing this will kick off the LOCKED rule again
1086 modify($operation) {};
1090 // Its not finished yet (i.e. expecting more Response objects)
1092 // Or possibly it is a leftover response that we timed the request out previously
1096 // We are going to retract these objects from memory
1104 * This rule responds to VFC Response Events
1107 rule "${policyName}.VFC.RESPONSE"
1109 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1110 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1111 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1112 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1113 requestID == $event.getRequestId() )
1114 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1115 onset.getRequestId() == $event.getRequestId() )
1116 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1117 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1118 $lock : TargetLock (requestID == $event.getRequestId())
1119 $response : VFCResponse( requestId.toString() == $event.getRequestId().toString() )
1121 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1122 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1123 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1124 $params.getClosedLoopControlName(), drools.getRule().getName(),
1125 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1127 // Get the result of the operation
1129 PolicyResult policyResult = $operation.onResponse($response);
1130 if (policyResult != null) {
1132 // This Operation has completed, construct a notification showing our results
1134 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1135 notification.setFrom("policy");
1136 notification.setPolicyName(drools.getRule().getName());
1137 notification.setPolicyScope("${policyScope}");
1138 notification.setPolicyVersion("${policyVersion}");
1139 notification.setMessage($operation.getOperationHistory());
1140 notification.setHistory($operation.getHistory());
1142 // Ensure the operation is complete
1144 if ($operation.isOperationComplete() == true) {
1146 // It is complete, remove it from memory
1148 retract($operation);
1150 // We must also retract the timer object
1151 // NOTE: We could write a Rule to do this
1155 // Complete the operation
1157 modify($manager) {finishOperation($operation)};
1160 // Just doing this will kick off the LOCKED rule again
1162 modify($operation) {};
1166 // Its not finished yet (i.e. expecting more Response objects)
1168 // Or possibly it is a leftover response that we timed the request out previously
1172 // We are going to retract these objects from memory
1180 * This rule responds to SDNC Response Events
1184 rule "${policyName}.SDNC.RESPONSE"
1186 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1187 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1188 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1189 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1190 requestID == $event.getRequestId() )
1191 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1192 onset.getRequestId() == $event.getRequestId() )
1193 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1194 requestID == $event.getRequestId().toString(), timerType == "Operation", !expired )
1195 $lock : TargetLock (requestID == $event.getRequestId())
1196 $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1198 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1199 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1200 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1201 $params.getClosedLoopControlName(), drools.getRule().getName(),
1202 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1204 // Get the result of the operation
1206 PolicyResult policyResult = $operation.onResponse($response);
1207 if (policyResult != null) {
1209 // This Operation has completed, construct a notification showing our results
1211 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1212 notification.setFrom("policy");
1213 notification.setPolicyName(drools.getRule().getName());
1214 notification.setPolicyScope("${policyScope}");
1215 notification.setPolicyVersion("${policyVersion}");
1216 notification.setMessage($operation.getOperationHistory());
1217 notification.setHistory($operation.getHistory());
1219 // Ensure the operation is complete
1221 if ($operation.isOperationComplete()) {
1223 // It is complete, remove it from memory
1225 retract($operation);
1227 // We must also retract the timer object
1228 // NOTE: We could write a Rule to do this
1232 // Complete the operation
1234 modify($manager) {finishOperation($operation)};
1237 // Just doing this will kick off the LOCKED rule again
1239 modify($operation) {};
1243 // Its not finished yet (i.e. expecting more Response objects)
1245 // Or possibly it is a leftover response that we timed the request out previously
1249 // We are going to retract these objects from memory
1257 * This manages a single timer.
1258 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1261 rule "${policyName}.TIMER.FIRED"
1262 timer (expr: $timeout)
1264 $timer : ControlLoopTimer($timeout : delay, !expired)
1266 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1267 logger.info("This is ${policyName}.TIMER.FIRED");
1268 modify($timer){setExpired(true)};
1273 * This is the timer that manages the timeout for an individual operation.
1276 rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT"
1278 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1279 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1280 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1281 requestID == $event.getRequestId() )
1282 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1283 onset.getRequestId() == $event.getRequestId() )
1284 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1285 requestID == $event.getRequestId().toString(), expired, timerType == "Operation" )
1286 $lock : TargetLock (requestID == $event.getRequestId())
1289 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1290 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1291 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1292 $params.getClosedLoopControlName(), drools.getRule().getName(),
1293 $event, $manager, $operation, $lock, $operation, $opTimer);
1296 // Tell it its timed out
1298 $operation.setOperationHasTimedOut();
1300 // Create a notification for it ("DB Write - end operation")
1302 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1303 notification.setFrom("policy");
1304 notification.setPolicyName(drools.getRule().getName());
1305 notification.setPolicyScope("${policyScope}");
1306 notification.setPolicyVersion("${policyVersion}");
1307 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1308 notification.setMessage($operation.getOperationHistory());
1309 notification.setHistory($operation.getHistory());
1311 // Let interested parties know
1313 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1315 // Get rid of the timer
1319 // Ensure the operation is complete
1321 if ($operation.isOperationComplete() == true) {
1323 // It is complete, remove it from memory
1325 retract($operation);
1327 // Complete the operation
1329 modify($manager) {finishOperation($operation)};
1332 // Just doing this will kick off the LOCKED rule again
1334 modify($operation) {};
1340 * This is the timer that manages the overall control loop timeout.
1343 rule "${policyName}.EVENT.MANAGER.TIMEOUT"
1345 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1346 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1347 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1348 requestID == $event.getRequestId() )
1349 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1350 requestID == $event.getRequestId().toString(), expired, timerType == "ClosedLoop" )
1353 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1354 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1356 logger.debug("{}: {}: event={}",
1357 $params.getClosedLoopControlName(), drools.getRule().getName(),
1360 // Tell the Event Manager it has timed out
1362 VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1363 if (notification != null) {
1364 notification.setFrom("policy");
1365 notification.setPolicyName(drools.getRule().getName());
1366 notification.setPolicyScope("${policyScope}");
1367 notification.setPolicyVersion("${policyVersion}");
1369 // Let interested parties know
1371 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1374 // Retract the event
1381 * This rule cleans up the manager and other objects after an event has
1385 rule "${policyName}.EVENT.MANAGER.CLEANUP"
1387 $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestID() )
1388 $operations : LinkedList()
1389 from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
1390 onset.getRequestId() == $requestId ) )
1391 $timers : LinkedList()
1392 from collect( ControlLoopTimer( closedLoopControlName == $clName,
1393 requestID == $requestId.toString() ) )
1394 $locks : LinkedList()
1395 from collect( TargetLock (requestID == $requestId) )
1396 not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1399 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1400 logger.info("{}: {}", $clName, drools.getRule().getName());
1402 logger.debug("{}: {}: manager={} timers={} operations={}",
1403 $clName, drools.getRule().getName(),
1404 $manager, $timers.size(), $operations.size());
1407 // Retract EVERYTHING
1411 for(Object manager: $operations) {
1412 retract((ControlLoopOperationManager) manager);
1414 for(Object timer: $timers) {
1415 retract((ControlLoopTimer) timer);
1417 for(Object lock: $locks) {
1418 TargetLock tgt = (TargetLock) lock;
1420 // Ensure we release the lock
1422 PolicyGuard.unlockTarget(tgt);
1429 * This rule will clean up any rogue onsets where there is no
1430 * ControlLoopParams object corresponding to the onset event.
1433 rule "${policyName}.EVENT.CLEANUP"
1435 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1436 not ( Params( getClosedLoopControlName() == $clName) )
1439 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1440 logger.info("{}: {}", $clName, drools.getRule().getName());
1441 logger.debug("{}: {}: orphan onset event={}",
1442 $clName, drools.getRule().getName(), $event);
1449 * When rules are deleted, the associated Params (and its subordinate objects)
1450 * remain in working memory, because there are no longer any rules to clean
1451 * them up. However, ANY time new rules are loaded, this rule will trigger
1452 * a clean-up of ALL Params, regardless of their name & yaml, thus removing
1453 * any that no longer have associated rules.
1454 * This has a higher salience so that we immediately check Params when the
1455 * rules change, before processing any events.
1458 rule "${policyName}.PARAMS.CHECKUP"
1461 Params( $clName: closedLoopControlName, $yaml: controlLoopYaml )
1464 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1465 logger.info("{}: {} : YAML=[{}]", $clName, drools.getRule().getName(), $yaml);
1467 ParamsCleaner cleaner = new ParamsCleaner();
1468 cleaner.setClosedLoopControlName($clName);
1469 cleaner.setControlLoopYaml($yaml);
1476 * This rule removes "cleaner" objects for rules that are still active, thus
1477 * preventing the associated Params objects from being removed. Any cleaners
1478 * that are left after this rule has fired will cause their corresponding Params
1480 * This has a higher salience so that we discard the cleaner before it has
1481 * a chance to force the removal of the associated Params.
1484 rule "${policyName}.CLEANER.ACTIVE"
1487 $cleaner: ParamsCleaner( getClosedLoopControlName() == "${closedLoopControlName}",
1488 getControlLoopYaml() == "${controlLoopYaml}" )
1491 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1492 logger.info("{}: {} : YAML=[{}]", $cleaner.getClosedLoopControlName(), drools.getRule().getName(),
1493 $cleaner.getControlLoopYaml());
1500 * This rule removes Params objects that no longer have associated rules; if a
1501 * Params still had associated rules, then the cleaner would have been removed
1502 * by those rules and thus this rule would not fire.
1503 * This has a higher salience so that we remove old Params before it causes any
1504 * events to be processed.
1507 rule "${policyName}.PARAMS.CLEANUP"
1510 $params: Params( $clName: closedLoopControlName, $yaml: controlLoopYaml )
1511 ParamsCleaner( getClosedLoopControlName() == $clName, getControlLoopYaml() == $yaml )
1514 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1515 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1516 $params.getControlLoopYaml());
1520 // Note: the cleaner may be needed for cleaning additional params, thus
1521 // we do not retract it here - we'll leave that to another rule
1526 * This rule removes "cleaner" objects when they're no longer needed.
1529 rule "${policyName}.CLEANER.CLEANUP"
1531 $cleaner: ParamsCleaner( )
1534 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1535 logger.info("{}: {} : YAML=[{}]", $cleaner.getClosedLoopControlName(), drools.getRule().getName(),
1536 $cleaner.getControlLoopYaml());