2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
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.params.ControlLoopParams;
24 import org.onap.policy.controlloop.VirtualControlLoopEvent;
25 import org.onap.policy.controlloop.VirtualControlLoopNotification;
26 import org.onap.policy.controlloop.ControlLoopEventStatus;
27 import org.onap.policy.controlloop.ControlLoopNotificationType;
28 import org.onap.policy.controlloop.ControlLoopLogger;
29 import org.onap.policy.controlloop.policy.PolicyResult;
30 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
31 import org.onap.policy.controlloop.policy.Policy;
32 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
33 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
34 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
35 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
36 import org.onap.policy.aai.AaiNqResponseWrapper;
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.SoRequest;
53 import org.onap.policy.so.SoResponseWrapper;
54 import org.onap.policy.sdnc.SdncRequest;
55 import org.onap.policy.sdnc.SdncManager;
56 import org.onap.policy.sdnc.SdncResponse;
57 import org.onap.policy.guard.PolicyGuard;
58 import org.onap.policy.guard.PolicyGuard.LockResult;
59 import org.onap.policy.guard.TargetLock;
60 import org.onap.policy.guard.GuardResult;
61 import org.onap.policy.guard.PolicyGuardRequest;
62 import org.onap.policy.guard.PolicyGuardResponse;
63 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
64 import org.onap.policy.guard.PolicyGuardXacmlHelper;
66 import org.yaml.snakeyaml.Yaml;
67 import org.yaml.snakeyaml.constructor.Constructor;
69 import org.slf4j.LoggerFactory;
70 import org.slf4j.Logger;
72 import java.time.Instant;
73 import java.util.LinkedList;
74 import java.util.Iterator;
76 import org.onap.policy.drools.system.PolicyEngine;
79 * This object is to provide support for timeouts
80 * due to a bug in drools' built-in timers
82 declare ControlLoopTimer
83 closedLoopControlName : String
87 //timerType is the type of timer: either "ClosedLoop" or "Operation"
93 * Called when the ControlLoopParams object has been inserted into working memory from the BRMSGW.
98 $params : ControlLoopParams()
101 // Note: globals have bad behavior when persistence is used,
102 // hence explicitly getting the logger vs using a global
104 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
105 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "."
106 + drools.getRule().getName(), $params.getControlLoopYaml());
111 * This rule responds to DCAE Events where there is no manager yet. Either it is
112 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
117 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
118 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
119 not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
120 requestId == $event.getRequestId() ) )
123 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
124 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
129 // Check the event, because we need it to not be null when
130 // we create the ControlLoopEventManager. The ControlLoopEventManager
131 // will do extra syntax checking as well check if the closed loop is disabled.
133 if ($event.getRequestId() == null) {
134 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
135 notification.setNotification(ControlLoopNotificationType.REJECTED);
136 notification.setFrom("policy");
137 notification.setMessage("Missing requestId");
138 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
139 notification.setPolicyScope($params.getPolicyScope());
140 notification.setPolicyVersion($params.getPolicyVersion());
143 // Let interested parties know
145 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
148 // Retract it from memory
151 } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
152 throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
155 // Create an EventManager
157 ControlLoopEventManager manager = new ControlLoopEventManager($clName, $event.getRequestId());
159 // Determine if EventManager can actively process the event
160 // (i.e. syntax, is_closed_loop_disabled checks etc.)
162 VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
163 notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
164 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
165 notification.setPolicyScope($params.getPolicyScope());
166 notification.setPolicyVersion($params.getPolicyVersion());
168 // Are we actively pursuing this event?
170 if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
172 // Insert Event Manager into memory, this will now kick off processing.
176 // Let interested parties know
178 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
180 // Setup the Overall Control Loop timer
182 ControlLoopTimer clTimer = new ControlLoopTimer();
183 clTimer.setTimerType("ClosedLoop");
184 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
185 clTimer.setRequestId($event.getRequestId().toString());
186 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
193 // Let interested parties know
195 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
197 // Retract it from memory
203 // Now that the manager is inserted into Drools working memory, we'll wait for
204 // another rule to fire in order to continue processing. This way we can also
205 // then screen for additional ONSET and ABATED events for this RequestId.
208 } catch (Exception e) {
209 logger.warn("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName(), e);
211 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
212 notification.setNotification(ControlLoopNotificationType.REJECTED);
213 notification.setMessage("Exception occurred: " + e.getMessage());
214 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
215 notification.setPolicyScope($params.getPolicyScope());
216 notification.setPolicyVersion($params.getPolicyVersion());
220 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
230 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
231 * is now created. We can start processing the yaml specification via the Event Manager.
236 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
237 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
238 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
239 requestId == $event.getRequestId() )
240 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
241 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
244 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
245 logger.info("{}: {}: event={} manager={} clTimer={}",
246 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
247 $event, $manager, $clTimer);
251 // Check which event this is.
253 ControlLoopEventManager.NewEventStatus eventStatus = $manager.onNewEvent($event);
255 // Check what kind of event this is
257 if (eventStatus == NewEventStatus.SUBSEQUENT_ONSET) {
259 // We don't care about subsequent onsets
261 logger.info("{}: {}: subsequent onset",
262 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
266 if (eventStatus == NewEventStatus.SYNTAX_ERROR) {
268 // Ignore any bad syntax events
270 logger.warn("{}: {}: syntax error",
271 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
276 // We only want the initial ONSET event in memory,
277 // all the other events need to be retracted to support
278 // cleanup and avoid the other rules being fired for this event.
280 if (eventStatus != NewEventStatus.FIRST_ONSET) {
281 logger.warn("{}: {}: no first onset",
282 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
286 logger.debug("{}: {}: target={}", $clName,
287 $params.getPolicyName() + "." + drools.getRule().getName(), $event.getTarget());
289 // Now start seeing if we need to process this event
293 // Check if this is a Final Event
295 VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
298 if (notification != null) {
300 // Its final, but are we waiting for abatement?
302 if ($manager.getNumAbatements() > 0) {
303 logger.info("{}: {}: abatement received for {}. Closing the control loop",
304 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
305 $event.getRequestId());
306 notification.setFrom("policy");
307 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
308 notification.setPolicyScope($params.getPolicyScope());
309 notification.setPolicyVersion($params.getPolicyVersion());
311 // In this case, we are done
313 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
317 TargetLock lock = $manager.unlockCurrentOperation();
319 logger.debug("{}: {}: retracting lock=", $clName,
320 $params.getPolicyName() + "." + drools.getRule().getName(), lock);
324 // Retract everything from memory
326 logger.info("{}: {}: retracting onset, manager, and timer",
327 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
329 retract($manager.getOnsetEvent());
331 // don't retract manager, etc. - a clean-up rule will do that
334 // TODO - what if we get subsequent Events for this RequestId?
335 // By default, it will all start over again. May be confusing for Ruby.
336 // Or, we could track this and then subsequently ignore the events
340 // Check whether we need to wait for abatement
342 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
343 logger.info("{}: {}: waiting for abatement ..",
344 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
346 logger.info("{}: {}: no abatement expect for {}. Closing the control loop",
347 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
348 $event.getRequestId());
350 notification.setFrom("policy");
351 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
352 notification.setPolicyScope($params.getPolicyScope());
353 notification.setPolicyVersion($params.getPolicyVersion());
356 // In this case, we are done
358 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
362 TargetLock lock = $manager.unlockCurrentOperation();
364 logger.debug("{}: {}: retracting lock=", $clName,
365 $params.getPolicyName() + "." + drools.getRule().getName(), lock);
369 // Retract everything from memory
371 logger.info("{}: {}: retracting onset, manager, and timer",
372 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
374 retract($manager.getOnsetEvent());
376 // don't retract manager, etc. - a clean-up rule will do that
381 // NOT final, so let's ask for the next operation
383 ControlLoopOperationManager operation = $manager.processControlLoop();
384 if (operation != null) {
386 // Let's ask for a lock right away
388 LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
389 logger.info("{}: {}: guard lock acquired={}",
390 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
392 if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
394 // insert the operation into memory
399 // insert operation timeout object
401 ControlLoopTimer opTimer = new ControlLoopTimer();
402 opTimer.setTimerType("Operation");
403 opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
404 opTimer.setRequestId($event.getRequestId().toString());
405 opTimer.setDelay(operation.getOperationTimeout().toString() + "s");
409 // Insert lock into memory
411 insert(result.getB());
414 logger.debug("The target resource {} is already processing",
415 $event.getAai().get($event.getTarget()));
416 notification = new VirtualControlLoopNotification($event);
417 notification.setNotification(ControlLoopNotificationType.REJECTED);
418 notification.setMessage("The target " + $event.getAai().get($event.getTarget())
419 + " is already locked");
420 notification.setFrom("policy");
421 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
422 notification.setPolicyScope($params.getPolicyScope());
423 notification.setPolicyVersion($params.getPolicyVersion());
425 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
429 // don't retract manager, etc. - a clean-up rule will do that
431 if(result.getB() != null) {
432 retract(result.getB());
435 logger.info("{}: {}: starting operation={}",
436 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
440 // Probably waiting for abatement
442 logger.info("{}: {}: no operation, probably waiting for abatement",
443 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
446 } catch (Exception e) {
447 logger.warn("{}: {}: unexpected",
449 $params.getPolicyName() + "." + drools.getRule().getName(), e);
451 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
452 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
453 notification.setMessage(e.getMessage());
454 notification.setFrom("policy");
455 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
456 notification.setPolicyScope($params.getPolicyScope());
457 notification.setPolicyVersion($params.getPolicyVersion());
459 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
463 // don't retract manager, etc. - a clean-up rule will do that
470 * Guard Permitted, let's send request to the actor.
473 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
475 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
476 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
477 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
478 requestId == $event.getRequestId() )
479 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
480 onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
481 $lock : TargetLock (requestId == $event.getRequestId())
482 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
483 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
486 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
487 logger.info("{}: {}: event={} manager={} operation={} lock={}",
488 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
489 $event, $manager, $operation, $lock);
491 Object request = null;
492 boolean caughtException = false;
495 request = $operation.startOperation($event);
497 if (request != null) {
498 logger.debug("{}: {}: starting operation ..",
500 $params.getPolicyName() + "." + drools.getRule().getName());
502 // Tell interested parties we are performing this Operation
504 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
505 notification.setNotification(ControlLoopNotificationType.OPERATION);
506 notification.setMessage($operation.getOperationMessage());
507 notification.setHistory($operation.getHistory());
508 notification.setFrom("policy");
509 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
510 notification.setPolicyScope($params.getPolicyScope());
511 notification.setPolicyVersion($params.getPolicyVersion());
513 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
515 switch ($operation.policy.getActor()){
519 if (request instanceof Request) {
520 PolicyEngine.manager.deliver("APPC-CL", request);
522 else if (request instanceof LcmRequestWrapper) {
523 PolicyEngine.manager.deliver("APPC-LCM-READ", request);
527 // at this point the AAI named query request should have already been made, the response
528 // recieved and used in the construction of the SO Request which is stored in operationRequest
530 if(request instanceof SoRequest) {
531 // Call SO. The response will be inserted into memory once it's received
532 SoActorServiceProvider.sendRequest($event.getRequestId().toString(), drools.getWorkingMemory(), request);
536 if (request instanceof VfcRequest) {
538 Thread t = new Thread(new VfcManager(drools.getWorkingMemory(), (VfcRequest)request));
543 if (request instanceof PciRequestWrapper) {
544 PolicyEngine.manager.deliver("SDNR-CL", request);
549 if (request instanceof SdncRequest) {
551 Thread t = new Thread(new SdncManager(drools.getWorkingMemory(), (SdncRequest)request));
558 // What happens if its null?
560 logger.warn("{}: {}: unexpected null operation request",
562 $params.getPolicyName() + "." + drools.getRule().getName());
563 if ("SO".equals($operation.policy.getActor())) {
566 modify($manager) {finishOperation($operation)};
568 else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
571 modify($manager) {finishOperation($operation)};
573 else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
576 modify($manager) {finishOperation($operation)};
580 } catch (Exception e) {
581 String msg = e.getMessage();
582 logger.warn("{}: {}: operation={}: AAI failure: {}",
584 $params.getPolicyName() + "." + drools.getRule().getName(),
586 $operation.setOperationHasException(msg);
588 if(request != null) {
590 // Create a notification for it ("DB Write - end operation")
592 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
593 notification.setFrom("policy");
594 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
595 notification.setPolicyScope($params.getPolicyScope());
596 notification.setPolicyVersion($params.getPolicyVersion());
597 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
598 notification.setMessage($operation.getOperationHistory());
599 notification.setHistory($operation.getHistory());
601 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
606 caughtException = true;
609 // Having the modify statement in the catch clause doesn't work for whatever reason
610 if (caughtException) {
611 modify($manager) {finishOperation($operation)};
618 * We were able to acquire a lock so now let's ask Xacml Guard whether
619 * we are allowed to proceed with the request to the actor.
622 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
624 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
625 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
626 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
627 requestId == $event.getRequestId() )
628 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
629 onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
630 $lock : TargetLock (requestId == $event.getRequestId())
633 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
634 logger.info("{}: {}: event={} manager={} operation={} lock={}",
635 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
636 $event, $manager, $operation, $lock);
639 // Sending notification that we are about to query Guard ("DB write - start operation")
641 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
642 notification.setNotification(ControlLoopNotificationType.OPERATION);
643 notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
644 + $operation.policy.getRecipe());
645 notification.setHistory($operation.getHistory());
646 notification.setFrom("policy");
647 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
648 notification.setPolicyScope($params.getPolicyScope());
649 notification.setPolicyVersion($params.getPolicyVersion());
651 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
654 // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
655 // just change guardEnabled to false.
657 // In order to use REST XACML, provide a URL instead of "" as a second argument
658 // to the CallGuardTask() and set the first argument to null
659 // (instead of XacmlPdpEngine).
662 // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
663 boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
667 Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
668 drools.getWorkingMemory(),
669 $event.getClosedLoopControlName(),
670 $operation.policy.getActor().toString(),
671 $operation.policy.getRecipe(),
672 $operation.getTargetEntity(),
673 $event.getRequestId().toString(),
675 AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
676 return(resp == null ? null : resp.countVfModules());
681 insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
687 // This rule will be triggered when a thread talking to the XACML Guard inserts a
688 // guardResponse object into the working memory
690 rule "GUARD.RESPONSE"
692 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
693 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
694 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
695 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
696 requestId == $event.getRequestId() )
697 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
698 onset.getRequestId() == $event.getRequestId() )
699 $lock : TargetLock (requestId == $event.getRequestId())
700 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
701 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
702 $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
705 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
706 logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
707 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
708 $event, $manager, $operation, $lock, $opTimer, $guardResponse);
711 //we will permit the operation if there was no Guard for it
712 if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
713 $guardResponse.setResult("Permit");
717 // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
719 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
720 notification.setNotification(ControlLoopNotificationType.OPERATION);
721 notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
722 + " is " + $guardResponse.getResult());
723 notification.setHistory($operation.getHistory());
724 notification.setFrom("policy");
725 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
726 notification.setPolicyScope($params.getPolicyScope());
727 notification.setPolicyVersion($params.getPolicyVersion());
729 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
731 if("Permit".equalsIgnoreCase($guardResponse.getResult())){
733 modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
736 //This is the Deny case
737 $operation.startOperation($event);
738 $operation.setOperationHasGuardDeny();
741 modify($manager) {finishOperation($operation)};
744 retract($guardResponse);
750 * This rule responds to APPC Response Events
752 * I would have like to be consistent and write the Response like this:
753 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
755 * However, no compile error was given. But a runtime error was given. I think
756 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
761 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
762 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
763 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
764 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
765 requestId == $event.getRequestId() )
766 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
767 onset.getRequestId() == $event.getRequestId() )
768 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
769 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
770 $lock : TargetLock (requestId == $event.getRequestId())
771 $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
774 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
775 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
776 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
777 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
778 $event, $manager, $operation, $lock, $opTimer, $response);
780 // Get the result of the operation
782 PolicyResult policyResult = $operation.onResponse($response);
783 if (policyResult != null) {
784 logger.debug("{}: {}: operation finished - result={}",
785 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
788 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
790 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
791 notification.setFrom("policy");
792 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
793 notification.setPolicyScope($params.getPolicyScope());
794 notification.setPolicyVersion($params.getPolicyVersion());
795 notification.setMessage($operation.getOperationHistory());
796 notification.setHistory($operation.getHistory());
797 if (policyResult.equals(PolicyResult.SUCCESS)) {
798 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
800 // Let interested parties know
802 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
804 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
806 // Let interested parties know
808 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
811 // Ensure the operation is complete
813 if ($operation.isOperationComplete() == true) {
815 // It is complete, remove it from memory
819 // We must also retract the timer object
820 // NOTE: We could write a Rule to do this
824 // Complete the operation
826 modify($manager) {finishOperation($operation)};
829 // Just doing this will kick off the LOCKED rule again
831 modify($operation) {};
835 // Its not finished yet (i.e. expecting more Response objects)
837 // Or possibly it is a leftover response that we timed the request out previously
841 // We are going to retract these objects from memory
848 * The problem with Responses is that they don't have a controlLoopControlName
849 * field in them, so the only way to attach them is via RequestId. If we have multiple
850 * control loop .drl's loaded in the same container, we need to be sure the cleanup
851 * rules don't remove Responses for other control loops.
854 rule "APPC.RESPONSE.CLEANUP"
856 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
857 $response : Response($id : getCommonHeader().RequestId )
858 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
861 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
862 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
863 logger.debug("{}: {}: orphan appc response={}",
864 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
874 * This rule responds to APPC Response Events using the new LCM interface provided by appc
877 rule "APPC.LCM.RESPONSE"
879 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
880 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
881 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
882 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
883 requestId == $event.getRequestId() )
884 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
885 onset.getRequestId() == $event.getRequestId() )
886 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
887 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
888 $lock : TargetLock (requestId == $event.getRequestId())
889 $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
892 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
893 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
894 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
895 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
896 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
899 // Get the result of the operation
901 PolicyResult policyResult = $operation.onResponse($response);
902 if (policyResult != null) {
903 logger.debug("{}: {}: operation finished - result={}",
904 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
908 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
910 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
911 notification.setFrom("policy");
912 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
913 notification.setPolicyScope($params.getPolicyScope());
914 notification.setPolicyVersion($params.getPolicyVersion());
915 notification.setMessage($operation.getOperationHistory());
916 notification.setHistory($operation.getHistory());
917 if (policyResult.equals(PolicyResult.SUCCESS)) {
918 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
920 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
922 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
924 // Ensure the operation is complete
926 if ($operation.isOperationComplete() == true) {
928 // It is complete, remove it from memory
932 // We must also retract the timer object
933 // NOTE: We could write a Rule to do this
937 // Complete the operation
939 modify($manager) {finishOperation($operation)};
942 // Just doing this will kick off the LOCKED rule again
944 modify($operation) {};
948 // Its not finished yet (i.e. expecting more Response objects)
950 // Or possibly it is a leftover response that we timed the request out previously
954 // We are going to retract these objects from memory
961 * Clean Up any lingering LCM reponses
964 rule "APPC.LCM.RESPONSE.CLEANUP"
966 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
967 $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
968 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
971 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
972 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
973 logger.debug("{}: {}: orphan appc response={}",
974 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
983 * This rule responds to SO Response Events
988 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
989 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
990 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
991 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
992 requestId == $event.getRequestId() )
993 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
994 onset.getRequestId() == $event.getRequestId() )
995 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
996 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
997 $lock : TargetLock (requestId == $event.getRequestId())
998 $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
1001 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1002 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1003 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1004 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1005 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1007 // Get the result of the operation
1009 PolicyResult policyResult = $operation.onResponse($response);
1010 if (policyResult != null) {
1011 logger.debug("{}: {}: operation finished - result={}",
1012 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1016 // This Operation has completed, construct a notification showing our results
1018 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1019 notification.setFrom("policy");
1020 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1021 notification.setPolicyScope($params.getPolicyScope());
1022 notification.setPolicyVersion($params.getPolicyVersion());
1023 notification.setMessage($operation.getOperationHistory());
1024 notification.setHistory($operation.getHistory());
1025 if (policyResult.equals(PolicyResult.SUCCESS)) {
1026 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1028 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1031 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1033 // Ensure the operation is complete
1035 if ($operation.isOperationComplete() == true) {
1037 // It is complete, remove it from memory
1039 retract($operation);
1041 // We must also retract the timer object
1042 // NOTE: We could write a Rule to do this
1046 // Complete the operation
1048 modify($manager) {finishOperation($operation)};
1051 // Just doing this will kick off the LOCKED rule again
1053 modify($operation) {};
1057 // Its not finished yet (i.e. expecting more Response objects)
1059 // Or possibly it is a leftover response that we timed the request out previously
1063 // We are going to retract these objects from memory
1071 * This rule responds to VFC Response Events
1076 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1077 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1078 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1079 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1080 requestId == $event.getRequestId() )
1081 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1082 onset.getRequestId() == $event.getRequestId() )
1083 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1084 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1085 $lock : TargetLock (requestId == $event.getRequestId())
1086 $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1088 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1089 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1090 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1091 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1092 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1094 // Get the result of the operation
1096 PolicyResult policyResult = $operation.onResponse($response);
1097 if (policyResult != null) {
1099 // This Operation has completed, construct a notification showing our results
1101 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1102 notification.setFrom("policy");
1103 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1104 notification.setPolicyScope($params.getPolicyScope());
1105 notification.setPolicyVersion($params.getPolicyVersion());
1106 notification.setMessage($operation.getOperationHistory());
1107 notification.setHistory($operation.getHistory());
1109 // Ensure the operation is complete
1111 if ($operation.isOperationComplete() == true) {
1113 // It is complete, remove it from memory
1115 retract($operation);
1117 // We must also retract the timer object
1118 // NOTE: We could write a Rule to do this
1122 // Complete the operation
1124 modify($manager) {finishOperation($operation)};
1127 // Just doing this will kick off the LOCKED rule again
1129 modify($operation) {};
1133 // Its not finished yet (i.e. expecting more Response objects)
1135 // Or possibly it is a leftover response that we timed the request out previously
1139 // We are going to retract these objects from memory
1147 * This rule responds to SDNC Response Events
1150 rule "SDNC.RESPONSE"
1152 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1153 $event : VirtualControlLoopEvent( closedLoopControlName == $clName, closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1154 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestId == $event.getRequestId() )
1155 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId() )
1156 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1157 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1158 $lock : TargetLock (requestId == $event.getRequestId())
1159 $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1161 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1162 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1163 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1164 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1165 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1167 // Get the result of the operation
1169 PolicyResult policyResult = $operation.onResponse($response);
1170 if (policyResult != null) {
1172 // This Operation has completed, construct a notification showing our results
1174 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1175 notification.setFrom("policy");
1176 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1177 notification.setPolicyScope($params.getPolicyScope());
1178 notification.setPolicyVersion($params.getPolicyVersion());
1179 notification.setMessage($operation.getOperationHistory());
1180 notification.setHistory($operation.getHistory());
1182 // Ensure the operation is complete
1184 if ($operation.isOperationComplete()) {
1186 // It is complete, remove it from memory
1188 retract($operation);
1190 // We must also retract the timer object
1191 // NOTE: We could write a Rule to do this
1195 // Complete the operation
1197 modify($manager) {finishOperation($operation)};
1200 // Just doing this will kick off the LOCKED rule again
1202 modify($operation) {};
1206 // Its not finished yet (i.e. expecting more Response objects)
1208 // Or possibly it is a leftover response that we timed the request out previously
1212 // We are going to retract these objects from memory
1220 * This manages a single timer.
1221 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1225 timer (expr: $timeout)
1227 $timer : ControlLoopTimer($timeout : delay, !expired)
1229 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1230 logger.info("This is TIMER.FIRED");
1231 modify($timer){setExpired(true)};
1236 * This is the timer that manages the timeout for an individual operation.
1239 rule "EVENT.MANAGER.OPERATION.TIMEOUT"
1241 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1242 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1243 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1244 requestId == $event.getRequestId() )
1245 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1246 onset.getRequestId() == $event.getRequestId() )
1247 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1248 requestId == $event.getRequestId().toString(), timerType == "Operation", expired )
1249 $lock : TargetLock (requestId == $event.getRequestId())
1252 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1253 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1254 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
1255 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1256 $event, $manager, $operation, $lock, $operation, $opTimer);
1259 // Tell it its timed out
1261 $operation.setOperationHasTimedOut();
1263 // Create a notification for it ("DB Write - end operation")
1265 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1266 notification.setFrom("policy");
1267 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1268 notification.setPolicyScope($params.getPolicyScope());
1269 notification.setPolicyVersion($params.getPolicyVersion());
1270 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1271 notification.setMessage($operation.getOperationHistory());
1272 notification.setHistory($operation.getHistory());
1274 // Let interested parties know
1276 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1278 // Get rid of the timer
1282 // Ensure the operation is complete
1284 if ($operation.isOperationComplete() == true) {
1286 // It is complete, remove it from memory
1288 retract($operation);
1290 // Complete the operation
1292 modify($manager) {finishOperation($operation)};
1295 // Just doing this will kick off the LOCKED rule again
1297 modify($operation) {};
1303 * This is the timer that manages the overall control loop timeout.
1306 rule "EVENT.MANAGER.TIMEOUT"
1308 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1309 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1310 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1311 requestId == $event.getRequestId() )
1312 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1313 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", expired )
1316 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1317 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1319 logger.debug("{}: {}: event={}",
1320 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1323 // Tell the Event Manager it has timed out
1325 VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1326 if (notification != null) {
1327 notification.setFrom("policy");
1328 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1329 notification.setPolicyScope($params.getPolicyScope());
1330 notification.setPolicyVersion($params.getPolicyVersion());
1332 // Let interested parties know
1334 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1337 // Retract the event
1344 * This rule cleans up the manager and other objects after an event has
1348 rule "EVENT.MANAGER.CLEANUP"
1350 $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
1351 $operations : LinkedList()
1352 from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
1353 onset.getRequestId() == $requestId ) )
1354 $timers : LinkedList()
1355 from collect( ControlLoopTimer( closedLoopControlName == $clName,
1356 requestId == $requestId.toString() ) )
1357 $locks : LinkedList()
1358 from collect( TargetLock (requestId == $requestId) )
1359 not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1362 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1363 logger.info("{}: {}", $clName, drools.getRule().getName());
1365 logger.debug("{}: {}: manager={} timers={} operations={}",
1366 $clName, drools.getRule().getName(),
1367 $manager, $timers.size(), $operations.size());
1370 // Retract EVERYTHING
1374 for(Object manager: $operations) {
1375 retract((ControlLoopOperationManager) manager);
1377 for(Object timer: $timers) {
1378 retract((ControlLoopTimer) timer);
1380 for(Object lock: $locks) {
1381 TargetLock tgt = (TargetLock) lock;
1383 // Ensure we release the lock
1385 PolicyGuard.unlockTarget(tgt);
1392 * This rule will clean up any rogue onsets where there is no
1393 * ControlLoopParams object corresponding to the onset event.
1396 rule "EVENT.CLEANUP"
1398 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1399 not ( ControlLoopParams( getClosedLoopControlName() == $clName) )
1402 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1403 logger.info("{}: {}", $clName, drools.getRule().getName());
1404 logger.debug("{}: {}: orphan onset event={}",
1405 $clName, drools.getRule().getName(), $event);
1412 * This rule responds to SDNR Response Events.
1415 rule "SDNR.RESPONSE"
1417 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1418 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1419 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1420 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1421 requestId == $event.getRequestId() )
1422 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1423 onset.getRequestId() == $event.getRequestId() )
1424 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1425 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1426 $lock : TargetLock (requestId == $event.getRequestId())
1427 $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1430 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1431 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1432 logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
1433 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1434 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1437 // Get the result of the operation
1439 PolicyResult policyResult = $operation.onResponse($response);
1440 if (policyResult != null) {
1441 logger.debug("{}: {}: operation finished - result={}",
1442 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1446 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1448 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1449 notification.setFrom("policy");
1450 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1451 notification.setPolicyScope($params.getPolicyScope());
1452 notification.setPolicyVersion($params.getPolicyVersion());
1453 notification.setMessage($operation.getOperationHistory());
1454 notification.setHistory($operation.getHistory());
1455 if (policyResult.equals(PolicyResult.SUCCESS)) {
1456 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1458 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1460 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1462 // Ensure the operation is complete
1464 if ($operation.isOperationComplete() == true) {
1466 // It is complete, remove it from memory
1468 retract($operation);
1470 // We must also retract the timer object
1471 // NOTE: We could write a Rule to do this
1475 // Complete the operation
1477 modify($manager) {finishOperation($operation)};
1480 // Just doing this will kick off the LOCKED rule again
1482 modify($operation) {};
1486 // Its not finished yet (i.e. expecting more Response objects)
1488 // Or possibly it is a leftover response that we timed the request out previously
1492 // We are going to retract these objects from memory
1499 * Clean Up any lingering SDNR reponses.
1502 rule "SDNR.RESPONSE.CLEANUP"
1504 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1505 $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1506 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1509 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1510 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1511 logger.debug("{}: {}: orphan sdnr response={}",
1512 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);