2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
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.NewEventStatus;
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.aai.AaiCqResponse;
37 import org.onap.policy.appc.Request;
38 import org.onap.policy.appc.Response;
39 import org.onap.policy.appc.CommonHeader;
40 import org.onap.policy.appclcm.LcmRequestWrapper;
41 import org.onap.policy.appclcm.LcmResponseWrapper;
42 import org.onap.policy.appclcm.LcmRequest;
43 import org.onap.policy.appclcm.LcmResponse;
44 import org.onap.policy.appclcm.LcmCommonHeader;
45 import org.onap.policy.sdnr.PciRequestWrapper;
46 import org.onap.policy.sdnr.PciResponseWrapper;
47 import org.onap.policy.sdnr.PciRequest;
48 import org.onap.policy.sdnr.PciResponse;
49 import org.onap.policy.vfc.VfcRequest;
50 import org.onap.policy.vfc.VfcResponse;
51 import org.onap.policy.vfc.VfcManager;
52 import org.onap.policy.so.SoManager;
53 import org.onap.policy.so.SoRequest;
54 import org.onap.policy.so.SoResponseWrapper;
55 import org.onap.policy.sdnc.SdncRequest;
56 import org.onap.policy.sdnc.SdncManager;
57 import org.onap.policy.sdnc.SdncResponse;
58 import org.onap.policy.guard.PolicyGuard;
59 import org.onap.policy.guard.PolicyGuard.LockResult;
60 import org.onap.policy.guard.TargetLock;
61 import org.onap.policy.guard.GuardResult;
62 import org.onap.policy.guard.PolicyGuardRequest;
63 import org.onap.policy.guard.PolicyGuardResponse;
64 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
65 import org.onap.policy.guard.PolicyGuardXacmlHelper;
67 import org.yaml.snakeyaml.Yaml;
68 import org.yaml.snakeyaml.constructor.Constructor;
70 import org.slf4j.LoggerFactory;
71 import org.slf4j.Logger;
73 import java.time.Instant;
74 import java.util.LinkedList;
75 import java.util.Iterator;
77 import org.onap.policy.drools.system.PolicyEngineConstants;
80 * This structure mimics the Params structure.
81 * Its only purpose is to allow management of
82 * rules by the PAP component..
83 * It has no use at runtime since the rules go by
84 * Params for matching purposes.
87 closedLoopControlName : String
88 controlLoopYaml : String
92 * Control Loop Identity
95 closedLoopControlName : String
96 controlLoopYaml : String
100 * Used to trigger clean up Params that no longer have associated rules.
102 declare ParamsInitCleaner
103 closedLoopControlName : String // only used when logging
107 * Used to clean up Params that no longer have associated rules.
109 declare ParamsCleaner
110 closedLoopControlName : String
111 controlLoopYaml : String
115 * This object is to provide support for timeouts
116 * due to a bug in drools' built-in timers
118 declare ControlLoopTimer
119 closedLoopControlName : String
123 //timerType is the type of timer: either "ClosedLoop" or "Operation"
129 * Called to insert the parameters into working memory for this Closed Loop policy. This is called
130 * once each time a closed loop is added or its YAML is updated.
131 * This has a higher salience so we can ensure that the Params is created before we have a chance to
132 * discard any events.
135 rule "${policyName}.SETUP"
138 not( Params( getClosedLoopControlName() == "${closedLoopControlName}",
139 getControlLoopYaml() == "${controlLoopYaml}" ) )
142 Params params = new Params();
143 params.setClosedLoopControlName("${closedLoopControlName}");
144 params.setControlLoopYaml("${controlLoopYaml}");
147 ParamsInitCleaner initCleaner = new ParamsInitCleaner();
148 initCleaner.setClosedLoopControlName("${closedLoopControlName}");
151 // Note: globals have bad behavior when persistence is used,
152 // hence explicitly getting the logger vs using a global
154 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
155 logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(),
156 params.getControlLoopYaml());
161 * This rule responds to DCAE Events where there is no manager yet. Either it is
162 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
165 rule "${policyName}.EVENT"
167 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
168 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
169 not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
170 requestId == $event.getRequestId() ) )
173 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
174 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
179 // Check the event, because we need it to not be null when
180 // we create the ControlLoopEventManager. The ControlLoopEventManager
181 // will do extra syntax checking as well check if the closed loop is disabled.
183 if ($event.getRequestId() == null) {
184 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
185 notification.setNotification(ControlLoopNotificationType.REJECTED);
186 notification.setFrom("policy");
187 notification.setMessage("Missing requestId");
188 notification.setPolicyName(drools.getRule().getName());
189 notification.setPolicyScope("${policyScope}");
190 notification.setPolicyVersion("${policyVersion}");
193 // Let interested parties know
195 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
198 // Retract it from memory
201 } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
202 throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
205 // Create an EventManager
207 ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(),
208 $event.getRequestId());
210 // Determine if EventManager can actively process the event
211 // (i.e. syntax, is_closed_loop_disabled checks etc.)
213 VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
214 notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
215 notification.setPolicyName(drools.getRule().getName());
216 notification.setPolicyScope("${policyScope}");
217 notification.setPolicyVersion("${policyVersion}");
219 // Are we actively pursuing this event?
221 if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
223 // Insert Event Manager into memory, this will now kick off processing.
227 // Let interested parties know
229 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
231 // Setup the Overall Control Loop timer
233 ControlLoopTimer clTimer = new ControlLoopTimer();
234 clTimer.setTimerType("ClosedLoop");
235 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
236 clTimer.setRequestId($event.getRequestId().toString());
237 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
244 // Let interested parties know
246 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
248 // Retract it from memory
254 // Now that the manager is inserted into Drools working memory, we'll wait for
255 // another rule to fire in order to continue processing. This way we can also
256 // then screen for additional ONSET and ABATED events for this RequestId.
259 } catch (Exception e) {
260 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
262 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
263 notification.setNotification(ControlLoopNotificationType.REJECTED);
264 notification.setMessage("Exception occurred: " + e.getMessage());
265 notification.setPolicyName(drools.getRule().getName());
266 notification.setPolicyScope("${policyScope}");
267 notification.setPolicyVersion("${policyVersion}");
271 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
281 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
282 * is now created. We can start processing the yaml specification via the Event Manager.
285 rule "${policyName}.EVENT.MANAGER"
287 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
288 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
289 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
290 requestId == $event.getRequestId() )
291 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
292 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
295 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
296 logger.info("{}: {}: event={} manager={} clTimer={}",
297 $params.getClosedLoopControlName(), drools.getRule().getName(),
298 $event, $manager, $clTimer);
302 // Check which event this is.
304 ControlLoopEventManager.NewEventStatus eventStatus = $manager.onNewEvent($event);
306 // Check what kind of event this is
308 if (eventStatus == NewEventStatus.SUBSEQUENT_ONSET) {
310 // We don't care about subsequent onsets
312 logger.info("{}: {}: subsequent onset",
313 $params.getClosedLoopControlName(), drools.getRule().getName());
317 if (eventStatus == NewEventStatus.SYNTAX_ERROR) {
319 // Ignore any bad syntax events
321 logger.warn("{}: {}: syntax error",
322 $params.getClosedLoopControlName(), drools.getRule().getName());
327 // We only want the initial ONSET event in memory,
328 // all the other events need to be retracted to support
329 // cleanup and avoid the other rules being fired for this event.
331 if (eventStatus != NewEventStatus.FIRST_ONSET) {
332 logger.warn("{}: {}: not first onset",
333 $params.getClosedLoopControlName(), drools.getRule().getName());
337 logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(),
338 drools.getRule().getName(), $event.getTarget());
340 // Now start seeing if we need to process this event
344 // Check if this is a Final Event
346 VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
349 if (notification != null) {
351 // Its final, but are we waiting for abatement?
353 if ($manager.getNumAbatements() > 0) {
354 logger.info("{}: {}: abatement received for {}. Closing the control loop",
355 $params.getClosedLoopControlName(), drools.getRule().getName(),
356 $event.getRequestId());
358 /// DB Write---end event processing for this RequestId()
359 $manager.commitAbatement("Event Abated","Closed");
361 notification.setFrom("policy");
362 notification.setPolicyName(drools.getRule().getName());
363 notification.setPolicyScope("${policyScope}");
364 notification.setPolicyVersion("${policyVersion}");
366 // In this case, we are done
368 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
372 TargetLock lock = $manager.unlockCurrentOperation();
374 logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(),
375 drools.getRule().getName(), lock);
379 // Retract everything from memory
381 logger.info("{}: {}: retracting onset, manager, and timer",
382 $params.getClosedLoopControlName(), drools.getRule().getName());
384 retract($manager.getOnsetEvent());
386 // don't retract manager, etc. - a clean-up rule will do that
389 // TODO - what if we get subsequent Events for this RequestId?
390 // By default, it will all start over again. May be confusing for Ruby.
391 // Or, we could track this and then subsequently ignore the events
395 // Check whether we need to wait for abatement
397 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
398 logger.info("{}: {}: waiting for abatement ..",
399 $params.getClosedLoopControlName(), drools.getRule().getName());
401 logger.info("{}: {}: no abatement expect for {}. Closing the control loop",
402 $params.getClosedLoopControlName(), drools.getRule().getName(),
403 $event.getRequestId());
405 notification.setFrom("policy");
406 notification.setPolicyName(drools.getRule().getName());
407 notification.setPolicyScope("${policyScope}");
408 notification.setPolicyVersion("${policyVersion}");
411 // In this case, we are done
413 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
417 TargetLock lock = $manager.unlockCurrentOperation();
419 logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(),
420 drools.getRule().getName(), lock);
424 // Retract everything from memory
426 logger.info("{}: {}: retracting onset, manager, and timer",
427 $params.getClosedLoopControlName(), drools.getRule().getName());
429 retract($manager.getOnsetEvent());
431 // don't retract manager, etc. - a clean-up rule will do that
436 // NOT final, so let's ask for the next operation
438 ControlLoopOperationManager operation = $manager.processControlLoop();
439 if (operation != null) {
441 // Let's ask for a lock right away
443 LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
444 logger.info("{}: {}: guard lock acquired={}",
445 $params.getClosedLoopControlName(), drools.getRule().getName(),
447 if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
449 // insert the operation into memory
453 // insert operation timeout object
455 ControlLoopTimer opTimer = new ControlLoopTimer();
456 opTimer.setTimerType("Operation");
457 opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
458 opTimer.setRequestId($event.getRequestId().toString());
459 Integer timeout = operation.getOperationTimeout();
460 opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
464 // Insert lock into memory
466 insert(result.getB());
468 logger.debug("The target resource {} is already processing",
469 $event.getAai().get($event.getTarget()));
470 notification = new VirtualControlLoopNotification($event);
471 notification.setNotification(ControlLoopNotificationType.REJECTED);
472 notification.setMessage("The target " + $event.getAai().get($event.getTarget())
473 + " is already locked");
474 notification.setFrom("policy");
475 notification.setPolicyName(drools.getRule().getName());
476 notification.setPolicyScope("${policyScope}");
477 notification.setPolicyVersion("${policyVersion}");
479 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
483 // don't retract manager, etc. - a clean-up rule will do that
485 if (result.getB() != null) {
486 retract(result.getB());
489 logger.info("{}: {}: starting operation={}",
490 $params.getClosedLoopControlName(), drools.getRule().getName(),
494 // Probably waiting for abatement
496 logger.info("{}: {}: no operation, probably waiting for abatement",
497 $params.getClosedLoopControlName(), drools.getRule().getName());
500 } catch (Exception e) {
501 logger.warn("{}: {}: unexpected",
502 $params.getClosedLoopControlName(),
503 drools.getRule().getName(), e);
505 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
506 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
507 notification.setMessage(e.getMessage());
508 notification.setFrom("policy");
509 notification.setPolicyName(drools.getRule().getName());
510 notification.setPolicyScope("${policyScope}");
511 notification.setPolicyVersion("${policyVersion}");
513 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
517 // don't retract manager, etc. - a clean-up rule will do that
524 * Guard Permitted, let's send request to the actor.
527 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
529 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
530 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
531 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
532 requestId == $event.getRequestId() )
533 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
534 onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
535 $lock : TargetLock (requestId == $event.getRequestId())
536 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
537 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
540 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
541 logger.info("{}: {}: event={} manager={} operation={} lock={}",
542 $params.getClosedLoopControlName(), drools.getRule().getName(),
543 $event, $manager, $operation, $lock);
545 Object request = null;
546 boolean caughtException = false;
549 request = $operation.startOperation($event);
551 if (request != null) {
552 logger.debug("{}: {}: starting operation ..",
553 $params.getClosedLoopControlName(), drools.getRule().getName());
555 // Tell interested parties we are performing this Operation
557 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
558 notification.setNotification(ControlLoopNotificationType.OPERATION);
559 notification.setMessage($operation.getOperationMessage());
560 notification.setHistory($operation.getHistory());
561 notification.setFrom("policy");
562 notification.setPolicyName(drools.getRule().getName());
563 notification.setPolicyScope("${policyScope}");
564 notification.setPolicyVersion("${policyVersion}");
566 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
568 switch ($operation.policy.getActor()){
571 if (request instanceof Request) {
572 PolicyEngineConstants.getManager().deliver("APPC-CL", request);
574 else if (request instanceof LcmRequestWrapper) {
575 PolicyEngineConstants.getManager().deliver("APPC-LCM-READ", request);
579 // at this point the AAI named query request should have already been made,
580 // the response recieved and used
581 // in the construction of the SO Request which is stored in operationRequest
583 if(request instanceof SoRequest) {
584 // Call SO. The response will be inserted into memory once it's received
585 class mySoCallback implements SoManager.SoCallback {
586 public void onSoResponseWrapper(SoResponseWrapper wrapper) {
587 drools.getWorkingMemory().insert(wrapper);
590 SoActorServiceProvider.sendRequest($event.getRequestId().toString(),
593 PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
594 PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
595 PolicyEngineConstants.getManager().getEnvironmentProperty("so.password"));
599 if (request instanceof VfcRequest) {
601 class myVfcCallback implements VfcManager.VfcCallback {
603 public void onResponse(VfcResponse responseError) {
604 drools.getWorkingMemory().insert(responseError);
608 Thread t = new Thread(new VfcManager(new myVfcCallback(),
610 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.url"),
611 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
612 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password")));
618 if (request instanceof SdncRequest) {
620 class mySdncCallback implements SdncManager.SdncCallback {
621 public void onCallback(SdncResponse response) {
622 drools.getWorkingMemory().insert(response);
626 Thread t = new Thread(new SdncManager(new mySdncCallback(),
627 (SdncRequest)request,
628 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
629 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
630 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
635 if (request instanceof PciRequestWrapper) {
636 PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
642 // What happens if its null?
644 logger.warn("{}: {}: unexpected null operation request",
645 $params.getClosedLoopControlName(),
646 drools.getRule().getName());
647 if ("SO".equals($operation.policy.getActor())) {
650 modify($manager) {finishOperation($operation)};
652 else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
655 modify($manager) {finishOperation($operation)};
657 else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
660 modify($manager) {finishOperation($operation)};
664 } catch (Exception e) {
665 String msg = e.getMessage();
666 logger.warn("{}: {}: operation={}: AAI failure: {}",
667 $params.getClosedLoopControlName(), drools.getRule().getName(),
669 $operation.setOperationHasException(msg);
671 if(request != null) {
673 // Create a notification for it ("DB Write - end operation")
675 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
676 notification.setFrom("policy");
677 notification.setPolicyName(drools.getRule().getName());
678 notification.setPolicyScope("${policyScope}");
679 notification.setPolicyVersion("${policyVersion}");
680 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
681 notification.setMessage($operation.getOperationHistory());
682 notification.setHistory($operation.getHistory());
684 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
689 caughtException = true;
692 // Having the modify statement in the catch clause doesn't work for whatever reason
693 if (caughtException) {
694 modify($manager) {finishOperation($operation)};
701 * We were able to acquire a lock so now let's ask Xacml Guard whether
702 * we are allowed to proceed with the request to the actor.
705 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
707 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
708 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
709 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
710 requestId == $event.getRequestId() )
711 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
712 onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
713 $lock : TargetLock (requestId == $event.getRequestId())
716 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
717 logger.info("{}: {}: event={} manager={} operation={} lock={}",
718 $params.getClosedLoopControlName(), drools.getRule().getName(),
719 $event, $manager, $operation, $lock);
722 // Sending notification that we are about to query Guard ("DB write - start operation")
724 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
725 notification.setNotification(ControlLoopNotificationType.OPERATION);
726 notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
727 + $operation.policy.getRecipe());
728 notification.setHistory($operation.getHistory());
729 notification.setFrom("policy");
730 notification.setPolicyName(drools.getRule().getName());
731 notification.setPolicyScope("${policyScope}");
732 notification.setPolicyVersion("${policyVersion}");
734 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
737 // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
738 // just change guardEnabled to false.
740 // In order to use REST XACML, provide a URL instead of "" as a second argument
741 // to the CallGuardTask() and set the first argument to null
742 // (instead of XacmlPdpEngine).
745 // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
746 boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("guard.disabled"));
747 boolean cqEnabled = "true".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("aai.customQuery"));
751 Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
752 drools.getWorkingMemory(),
753 $event.getClosedLoopControlName(),
754 $operation.policy.getActor().toString(),
755 $operation.policy.getRecipe(),
756 $operation.getTargetEntity(),
757 $event.getRequestId().toString(),
760 AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
761 return(resp == null ? null : resp.countVfModules());
764 AaiCqResponse resp_cq = $manager.getCqResponse($event);
765 if (resp_cq == null){
768 String custId = $operation.policy.getTarget().getModelCustomizationId();
769 String invId = $operation.policy.getTarget().getModelInvariantId();
770 String verId = $operation.policy.getTarget().getModelVersionId();
771 return resp_cq.getVfModuleCount(custId, invId, verId);
773 } catch (Exception e){
774 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
782 insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
788 // This rule will be triggered when a thread talking to the XACML Guard inserts a
789 // guardResponse object into the working memory
791 rule "${policyName}.GUARD.RESPONSE"
793 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
794 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
795 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
796 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
797 requestId == $event.getRequestId() )
798 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
799 onset.getRequestId() == $event.getRequestId() )
800 $lock : TargetLock (requestId == $event.getRequestId())
801 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
802 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
803 $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
806 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
807 logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
808 $params.getClosedLoopControlName(), drools.getRule().getName(),
809 $event, $manager, $operation, $lock, $opTimer, $guardResponse);
812 //we will permit the operation if there was no Guard for it
813 if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
814 $guardResponse.setResult("Permit");
818 // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
820 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
821 notification.setNotification(ControlLoopNotificationType.OPERATION);
822 notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
823 + " is " + $guardResponse.getResult());
824 notification.setHistory($operation.getHistory());
825 notification.setFrom("policy");
826 notification.setPolicyName(drools.getRule().getName());
827 notification.setPolicyScope("${policyScope}");
828 notification.setPolicyVersion("${policyVersion}");
830 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
832 if("Permit".equalsIgnoreCase($guardResponse.getResult())){
834 modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
837 //This is the Deny case
838 $operation.startOperation($event);
839 $operation.setOperationHasGuardDeny();
842 modify($manager) {finishOperation($operation)};
845 retract($guardResponse);
851 * This rule responds to APPC Response Events
853 * I would have like to be consistent and write the Response like this:
854 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
856 * However, no compile error was given. But a runtime error was given. I think
857 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
860 rule "${policyName}.APPC.RESPONSE"
862 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
863 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
864 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
865 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
866 requestId == $event.getRequestId() )
867 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
868 onset.getRequestId() == $event.getRequestId() )
869 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
870 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
871 $lock : TargetLock (requestId == $event.getRequestId())
872 $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
875 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
876 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
877 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
878 $params.getClosedLoopControlName(), drools.getRule().getName(),
879 $event, $manager, $operation, $lock, $opTimer, $response);
881 // Get the result of the operation
883 PolicyResult policyResult = $operation.onResponse($response);
884 if (policyResult != null) {
885 logger.debug("{}: {}: operation finished - result={}",
886 $params.getClosedLoopControlName(), drools.getRule().getName(),
889 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
891 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
892 notification.setFrom("policy");
893 notification.setPolicyName(drools.getRule().getName());
894 notification.setPolicyScope("${policyScope}");
895 notification.setPolicyVersion("${policyVersion}");
896 notification.setMessage($operation.getOperationHistory());
897 notification.setHistory($operation.getHistory());
898 if (policyResult.equals(PolicyResult.SUCCESS)) {
899 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
901 // Let interested parties know
903 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
905 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
907 // Let interested parties know
909 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
912 // Ensure the operation is complete
914 if ($operation.isOperationComplete() == true) {
916 // It is complete, remove it from memory
920 // We must also retract the timer object
921 // NOTE: We could write a Rule to do this
925 // Complete the operation
927 modify($manager) {finishOperation($operation)};
930 // Just doing this will kick off the LOCKED rule again
932 modify($operation) {};
936 // Its not finished yet (i.e. expecting more Response objects)
938 // Or possibly it is a leftover response that we timed the request out previously
942 // We are going to retract these objects from memory
949 * The problem with Responses is that they don't have a controlLoopControlName
950 * field in them, so the only way to attach them is via RequestId. If we have multiple
951 * control loop .drl's loaded in the same container, we need to be sure the cleanup
952 * rules don't remove Responses for other control loops.
955 rule "${policyName}.APPC.RESPONSE.CLEANUP"
957 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
958 $response : Response($id : getCommonHeader().RequestId )
959 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
962 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
963 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
964 logger.debug("{}: {}: orphan appc response={}",
965 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
975 * This rule responds to APPC Response Events using the new LCM interface provided by appc
978 rule "${policyName}.APPC.LCM.RESPONSE"
980 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
981 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
982 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
983 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
984 requestId == $event.getRequestId() )
985 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
986 onset.getRequestId() == $event.getRequestId() )
987 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
988 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
989 $lock : TargetLock (requestId == $event.getRequestId())
990 $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
993 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
994 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
995 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
996 $params.getClosedLoopControlName(), drools.getRule().getName(),
997 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1000 // Get the result of the operation
1002 PolicyResult policyResult = $operation.onResponse($response);
1003 if (policyResult != null) {
1004 logger.debug("{}: {}: operation finished - result={}",
1005 $params.getClosedLoopControlName(), drools.getRule().getName(),
1009 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1011 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1012 notification.setFrom("policy");
1013 notification.setPolicyName(drools.getRule().getName());
1014 notification.setPolicyScope("${policyScope}");
1015 notification.setPolicyVersion("${policyVersion}");
1016 notification.setMessage($operation.getOperationHistory());
1017 notification.setHistory($operation.getHistory());
1018 if (policyResult.equals(PolicyResult.SUCCESS)) {
1019 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1021 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1023 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1025 // Ensure the operation is complete
1027 if ($operation.isOperationComplete() == true) {
1029 // It is complete, remove it from memory
1031 retract($operation);
1033 // We must also retract the timer object
1034 // NOTE: We could write a Rule to do this
1038 // Complete the operation
1040 modify($manager) {finishOperation($operation)};
1043 // Just doing this will kick off the LOCKED rule again
1045 modify($operation) {};
1049 // Its not finished yet (i.e. expecting more Response objects)
1051 // Or possibly it is a leftover response that we timed the request out previously
1055 // We are going to retract these objects from memory
1062 * Clean Up any lingering LCM reponses
1065 rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
1067 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1068 $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1069 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1072 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1073 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1074 logger.debug("{}: {}: orphan appc response={}",
1075 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1084 * This rule responds to SDNR Response Events using the new interface provided by SDNR
1087 rule "${policyName}.SDNR.RESPONSE"
1089 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1090 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1091 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1092 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1093 requestId == $event.getRequestId() )
1094 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1095 onset.getRequestId() == $event.getRequestId() )
1096 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1097 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1098 $lock : TargetLock (requestId == $event.getRequestId())
1099 $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1102 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1103 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1104 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1105 $params.getClosedLoopControlName(), drools.getRule().getName(),
1106 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1109 // Get the result of the operation
1111 PolicyResult policyResult = $operation.onResponse($response);
1112 if (policyResult != null) {
1113 logger.debug("{}: {}: operation finished - result={}",
1114 $params.getClosedLoopControlName(), drools.getRule().getName(),
1118 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1120 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1121 notification.setFrom("policy");
1122 notification.setPolicyName(drools.getRule().getName());
1123 notification.setPolicyScope("${policyScope}");
1124 notification.setPolicyVersion("${policyVersion}");
1125 notification.setMessage($operation.getOperationHistory());
1126 notification.setHistory($operation.getHistory());
1127 if (policyResult.equals(PolicyResult.SUCCESS)) {
1128 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1130 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1132 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1134 // Ensure the operation is complete
1136 if ($operation.isOperationComplete()) {
1138 // It is complete, remove it from memory
1140 retract($operation);
1142 // We must also retract the timer object
1143 // NOTE: We could write a Rule to do this
1147 // Complete the operation
1149 modify($manager) {finishOperation($operation)};
1152 // Just doing this will kick off the LOCKED rule again
1154 modify($operation) {};
1158 // Its not finished yet (i.e. expecting more Response objects)
1160 // Or possibly it is a leftover response that we timed the request out previously
1164 // We are going to retract these objects from memory
1171 * Clean Up any lingering SDNR reponses
1174 rule "${policyName}.SDNR.RESPONSE.CLEANUP"
1176 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1177 $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1178 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1181 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1182 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1183 logger.debug("{}: {}: orphan SDNR response={}",
1184 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1193 * This rule responds to SO Response Events
1196 rule "${policyName}.SO.RESPONSE"
1198 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1199 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1200 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1201 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1202 requestId == $event.getRequestId() )
1203 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1204 onset.getRequestId() == $event.getRequestId() )
1205 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1206 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1207 $lock : TargetLock (requestId == $event.getRequestId())
1208 $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
1211 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1212 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1213 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1214 $params.getClosedLoopControlName(), drools.getRule().getName(),
1215 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1217 // Get the result of the operation
1219 PolicyResult policyResult = $operation.onResponse($response);
1220 if (policyResult != null) {
1221 logger.debug("{}: {}: operation finished - result={}",
1222 $params.getClosedLoopControlName(), drools.getRule().getName(),
1226 // This Operation has completed, construct a notification showing our results
1228 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1229 notification.setFrom("policy");
1230 notification.setPolicyName(drools.getRule().getName());
1231 notification.setPolicyScope("${policyScope}");
1232 notification.setPolicyVersion("${policyVersion}");
1233 notification.setMessage($operation.getOperationHistory());
1234 notification.setHistory($operation.getHistory());
1235 if (policyResult.equals(PolicyResult.SUCCESS)) {
1236 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1238 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1241 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1243 // Ensure the operation is complete
1245 if ($operation.isOperationComplete() == true) {
1247 // It is complete, remove it from memory
1249 retract($operation);
1251 // We must also retract the timer object
1252 // NOTE: We could write a Rule to do this
1256 // Complete the operation
1258 modify($manager) {finishOperation($operation)};
1261 // Just doing this will kick off the LOCKED rule again
1263 modify($operation) {};
1267 // Its not finished yet (i.e. expecting more Response objects)
1269 // Or possibly it is a leftover response that we timed the request out previously
1273 // We are going to retract these objects from memory
1281 * This rule responds to VFC Response Events
1284 rule "${policyName}.VFC.RESPONSE"
1286 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1287 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1288 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1289 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1290 requestId == $event.getRequestId() )
1291 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1292 onset.getRequestId() == $event.getRequestId() )
1293 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1294 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1295 $lock : TargetLock (requestId == $event.getRequestId())
1296 $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1298 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1299 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1300 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1301 $params.getClosedLoopControlName(), drools.getRule().getName(),
1302 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1304 // Get the result of the operation
1306 PolicyResult policyResult = $operation.onResponse($response);
1307 if (policyResult != null) {
1309 // This Operation has completed, construct a notification showing our results
1311 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1312 notification.setFrom("policy");
1313 notification.setPolicyName(drools.getRule().getName());
1314 notification.setPolicyScope("${policyScope}");
1315 notification.setPolicyVersion("${policyVersion}");
1316 notification.setMessage($operation.getOperationHistory());
1317 notification.setHistory($operation.getHistory());
1319 // Ensure the operation is complete
1321 if ($operation.isOperationComplete() == true) {
1323 // It is complete, remove it from memory
1325 retract($operation);
1327 // We must also retract the timer object
1328 // NOTE: We could write a Rule to do this
1332 // Complete the operation
1334 modify($manager) {finishOperation($operation)};
1337 // Just doing this will kick off the LOCKED rule again
1339 modify($operation) {};
1343 // Its not finished yet (i.e. expecting more Response objects)
1345 // Or possibly it is a leftover response that we timed the request out previously
1349 // We are going to retract these objects from memory
1357 * This rule responds to SDNC Response Events
1361 rule "${policyName}.SDNC.RESPONSE"
1363 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1364 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1365 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1366 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1367 requestId == $event.getRequestId() )
1368 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1369 onset.getRequestId() == $event.getRequestId() )
1370 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1371 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1372 $lock : TargetLock (requestId == $event.getRequestId())
1373 $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1375 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1376 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1377 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1378 $params.getClosedLoopControlName(), drools.getRule().getName(),
1379 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1381 // Get the result of the operation
1383 PolicyResult policyResult = $operation.onResponse($response);
1384 if (policyResult != null) {
1386 // This Operation has completed, construct a notification showing our results
1388 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1389 notification.setFrom("policy");
1390 notification.setPolicyName(drools.getRule().getName());
1391 notification.setPolicyScope("${policyScope}");
1392 notification.setPolicyVersion("${policyVersion}");
1393 notification.setMessage($operation.getOperationHistory());
1394 notification.setHistory($operation.getHistory());
1396 // Ensure the operation is complete
1398 if ($operation.isOperationComplete()) {
1400 // It is complete, remove it from memory
1402 retract($operation);
1404 // We must also retract the timer object
1405 // NOTE: We could write a Rule to do this
1409 // Complete the operation
1411 modify($manager) {finishOperation($operation)};
1414 // Just doing this will kick off the LOCKED rule again
1416 modify($operation) {};
1420 // Its not finished yet (i.e. expecting more Response objects)
1422 // Or possibly it is a leftover response that we timed the request out previously
1426 // We are going to retract these objects from memory
1434 * This manages a single timer.
1435 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1438 rule "${policyName}.TIMER.FIRED"
1439 timer (expr: $timeout)
1441 $timer : ControlLoopTimer($timeout : delay, !expired)
1443 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1444 logger.info("This is ${policyName}.TIMER.FIRED");
1445 modify($timer){setExpired(true)};
1450 * This is the timer that manages the timeout for an individual operation.
1453 rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT"
1455 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1456 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1457 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1458 requestId == $event.getRequestId() )
1459 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1460 onset.getRequestId() == $event.getRequestId() )
1461 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1462 requestId == $event.getRequestId().toString(), expired, timerType == "Operation" )
1463 $lock : TargetLock (requestId == $event.getRequestId())
1466 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1467 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1468 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1469 $params.getClosedLoopControlName(), drools.getRule().getName(),
1470 $event, $manager, $operation, $lock, $operation, $opTimer);
1473 // Tell it its timed out
1475 $operation.setOperationHasTimedOut();
1477 // Create a notification for it ("DB Write - end operation")
1479 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1480 notification.setFrom("policy");
1481 notification.setPolicyName(drools.getRule().getName());
1482 notification.setPolicyScope("${policyScope}");
1483 notification.setPolicyVersion("${policyVersion}");
1484 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1485 notification.setMessage($operation.getOperationHistory());
1486 notification.setHistory($operation.getHistory());
1488 // Let interested parties know
1490 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1492 // Get rid of the timer
1496 // Ensure the operation is complete
1498 if ($operation.isOperationComplete() == true) {
1500 // It is complete, remove it from memory
1502 retract($operation);
1504 // Complete the operation
1506 modify($manager) {finishOperation($operation)};
1509 // Just doing this will kick off the LOCKED rule again
1511 modify($operation) {};
1517 * This is the timer that manages the overall control loop timeout.
1520 rule "${policyName}.EVENT.MANAGER.TIMEOUT"
1522 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1523 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1524 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1525 requestId == $event.getRequestId() )
1526 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1527 requestId == $event.getRequestId().toString(), expired, timerType == "ClosedLoop" )
1530 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1531 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1533 logger.debug("{}: {}: event={}",
1534 $params.getClosedLoopControlName(), drools.getRule().getName(),
1537 // Tell the Event Manager it has timed out
1539 VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1540 if (notification != null) {
1541 notification.setFrom("policy");
1542 notification.setPolicyName(drools.getRule().getName());
1543 notification.setPolicyScope("${policyScope}");
1544 notification.setPolicyVersion("${policyVersion}");
1546 // Let interested parties know
1548 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1551 // Retract the event
1558 * This rule cleans up the manager and other objects after an event has
1562 rule "${policyName}.EVENT.MANAGER.CLEANUP"
1564 $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
1565 $operations : LinkedList()
1566 from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
1567 onset.getRequestId() == $requestId ) )
1568 $timers : LinkedList()
1569 from collect( ControlLoopTimer( closedLoopControlName == $clName,
1570 requestId == $requestId.toString() ) )
1571 $locks : LinkedList()
1572 from collect( TargetLock (requestId == $requestId) )
1573 not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1576 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1577 logger.info("{}: {}", $clName, drools.getRule().getName());
1579 logger.debug("{}: {}: manager={} timers={} operations={}",
1580 $clName, drools.getRule().getName(),
1581 $manager, $timers.size(), $operations.size());
1584 // Retract EVERYTHING
1588 for(Object manager: $operations) {
1589 retract((ControlLoopOperationManager) manager);
1591 for(Object timer: $timers) {
1592 retract((ControlLoopTimer) timer);
1594 for(Object lock: $locks) {
1595 TargetLock tgt = (TargetLock) lock;
1597 // Ensure we release the lock
1599 PolicyGuard.unlockTarget(tgt);
1606 * This rule will clean up any rogue onsets where there is no
1607 * ControlLoopParams object corresponding to the onset event.
1610 rule "${policyName}.EVENT.CLEANUP"
1612 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1613 not ( Params( getClosedLoopControlName() == $clName) )
1616 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1617 logger.info("{}: {}", $clName, drools.getRule().getName());
1618 logger.debug("{}: {}: orphan onset event={}",
1619 $clName, drools.getRule().getName(), $event);
1625 * Creates a cleaner for every Params object.
1626 * This has a higher salience so that it is fired before PARAMS.FINISHED in ANY policy.
1628 rule "${policyName}.PARAMS.CLEANING"
1632 ParamsInitCleaner( )
1635 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1636 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1637 $params.getControlLoopYaml());
1639 ParamsCleaner cleaner = new ParamsCleaner();
1640 cleaner.setClosedLoopControlName($params.getClosedLoopControlName());
1641 cleaner.setControlLoopYaml($params.getControlLoopYaml());
1646 * Finished creating cleaner objects, so remove the trigger.
1647 * This has a higher salience so that it is fired before processing any events.
1649 rule "${policyName}.PARAMS.FINISHED"
1652 $initCleaner: ParamsInitCleaner( )
1655 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1656 logger.info("{}: {}", $initCleaner.getClosedLoopControlName(), drools.getRule().getName());
1658 retract($initCleaner);
1662 * Identifies Params objects that are still active, removing their associated cleaners.
1663 * This should only leave one active Params object for each policy.
1664 * This has a higher salience so that it is fired before PARAMS.DELETE in ANY policy.
1666 rule "${policyName}.PARAMS.ACTIVE"
1669 $params: Params( getClosedLoopControlName() == "${closedLoopControlName}",
1670 getControlLoopYaml() == "${controlLoopYaml}" )
1671 $cleaner: ParamsCleaner( getClosedLoopControlName() == "${closedLoopControlName}",
1672 getControlLoopYaml() == "${controlLoopYaml}" )
1675 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1676 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1677 $params.getControlLoopYaml());
1683 * Delete Params objects that are not active (i.e., those that still have an associated
1685 * This has a higher salience so that it is fired before PARAMS.CLEANED in ANY policy.
1687 rule "${policyName}.PARAMS.DELETE"
1691 $cleaner: ParamsCleaner( getClosedLoopControlName() == $params.getClosedLoopControlName(),
1692 getControlLoopYaml() == $params.getControlLoopYaml() )
1695 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1696 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1697 $params.getControlLoopYaml());
1703 * Finished clean-up, so delete the cleaner objects.
1704 * This has a higher salience so that it is fired before processing any events.
1706 rule "${policyName}.PARAMS.CLEANED"
1709 $cleaner: ParamsCleaner( )
1712 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1713 logger.info("{}: {} : YAML=[{}]", $cleaner.getClosedLoopControlName(), drools.getRule().getName(),
1714 $cleaner.getControlLoopYaml());