2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Bell Canada.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.controlloop;
24 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
26 import org.onap.policy.controlloop.VirtualControlLoopEvent;
27 import org.onap.policy.controlloop.VirtualControlLoopNotification;
28 import org.onap.policy.controlloop.ControlLoopEventStatus;
29 import org.onap.policy.controlloop.ControlLoopNotificationType;
30 import org.onap.policy.controlloop.ControlLoopLogger;
31 import org.onap.policy.controlloop.policy.PolicyResult;
32 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
33 import org.onap.policy.controlloop.policy.Policy;
34 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
35 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
36 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
37 import org.onap.policy.controlloop.eventmanager.LockCallbackWorkingMemory;
38 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
39 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider;
40 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager;
41 import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
42 import org.onap.policy.aai.AaiNqResponseWrapper;
43 import org.onap.policy.aai.AaiCqResponse;
44 import org.onap.policy.appc.Request;
45 import org.onap.policy.appc.Response;
46 import org.onap.policy.appc.CommonHeader;
47 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
48 import org.onap.policy.cds.CdsResponse;
49 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
50 import org.onap.policy.cds.properties.CdsServerProperties;
51 import org.onap.policy.drools.utils.Pair;
52 import org.onap.policy.sdnr.PciRequestWrapper;
53 import org.onap.policy.sdnr.PciResponseWrapper;
54 import org.onap.policy.sdnr.PciRequest;
55 import org.onap.policy.sdnr.PciResponse;
56 import org.onap.policy.vfc.VfcRequest;
57 import org.onap.policy.vfc.VfcResponse;
58 import org.onap.policy.vfc.VfcManager;
59 import org.onap.policy.so.SoManager;
60 import org.onap.policy.so.SoRequest;
61 import org.onap.policy.so.SoResponseWrapper;
62 import org.onap.policy.sdnc.SdncRequest;
63 import org.onap.policy.sdnc.SdncManager;
64 import org.onap.policy.sdnc.SdncResponse;
65 import org.onap.policy.drools.core.lock.Lock;
66 import org.onap.policy.guard.PolicyGuardRequest;
67 import org.onap.policy.guard.PolicyGuardResponse;
68 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
69 import org.onap.policy.guard.PolicyGuardXacmlHelper;
71 import org.yaml.snakeyaml.Yaml;
72 import org.yaml.snakeyaml.constructor.Constructor;
74 import org.slf4j.LoggerFactory;
75 import org.slf4j.Logger;
77 import java.time.Instant;
78 import java.util.LinkedList;
79 import java.util.Iterator;
81 import org.onap.policy.drools.system.PolicyEngineConstants;
84 * This structure mimics the Params structure.
85 * Its only purpose is to allow management of
86 * rules by the PAP component..
87 * It has no use at runtime since the rules go by
88 * Params for matching purposes.
91 closedLoopControlName : String
92 controlLoopYaml : String
96 * Control Loop Identity
99 closedLoopControlName : String
100 controlLoopYaml : String
104 * Used to trigger clean up Params that no longer have associated rules.
106 declare ParamsInitCleaner
107 closedLoopControlName : String // only used when logging
111 * Used to clean up Params that no longer have associated rules.
113 declare ParamsCleaner
114 closedLoopControlName : String
115 controlLoopYaml : String
119 * This object is to provide support for timeouts
120 * due to a bug in drools' built-in timers
122 declare ControlLoopTimer
123 closedLoopControlName : String
127 //timerType is the type of timer: either "ClosedLoop" or "Operation"
133 * Called to insert the parameters into working memory for this Closed Loop policy. This is called
134 * once each time a closed loop is added or its YAML is updated.
135 * This has a higher salience so we can ensure that the Params is created before we have a chance to
136 * discard any events.
139 rule "${policyName}.SETUP"
142 not( Params( getClosedLoopControlName() == "${closedLoopControlName}",
143 getControlLoopYaml() == "${controlLoopYaml}" ) )
146 Params params = new Params();
147 params.setClosedLoopControlName("${closedLoopControlName}");
148 params.setControlLoopYaml("${controlLoopYaml}");
151 ParamsInitCleaner initCleaner = new ParamsInitCleaner();
152 initCleaner.setClosedLoopControlName("${closedLoopControlName}");
155 // Note: globals have bad behavior when persistence is used,
156 // hence explicitly getting the logger vs using a global
158 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
159 logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(),
160 params.getControlLoopYaml());
165 * This rule responds to DCAE Events where there is no manager yet. Either it is
166 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
169 rule "${policyName}.EVENT"
171 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
172 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
173 not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
174 requestId == $event.getRequestId() ) )
177 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
178 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
183 // Check the event, because we need it to not be null when
184 // we create the ControlLoopEventManager. The ControlLoopEventManager
185 // will do extra syntax checking as well check if the closed loop is disabled.
187 if ($event.getRequestId() == null) {
188 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
189 notification.setNotification(ControlLoopNotificationType.REJECTED);
190 notification.setFrom("policy");
191 notification.setMessage("Missing requestId");
192 notification.setPolicyName(drools.getRule().getName());
193 notification.setPolicyScope("${policyScope}");
194 notification.setPolicyVersion("${policyVersion}");
197 // Let interested parties know
199 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
202 // Retract it from memory
205 } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
206 throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
209 // Create an EventManager
211 ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(),
212 $event.getRequestId());
214 // Determine if EventManager can actively process the event
215 // (i.e. syntax, is_closed_loop_disabled checks etc.)
217 VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
218 notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
219 notification.setPolicyName(drools.getRule().getName());
220 notification.setPolicyScope("${policyScope}");
221 notification.setPolicyVersion("${policyVersion}");
223 // Are we actively pursuing this event?
225 if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
227 // Insert Event Manager into memory, this will now kick off processing.
231 // Let interested parties know
233 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
235 // Setup the Overall Control Loop timer
237 ControlLoopTimer clTimer = new ControlLoopTimer();
238 clTimer.setTimerType("ClosedLoop");
239 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
240 clTimer.setRequestId($event.getRequestId().toString());
241 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
248 // Let interested parties know
250 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
252 // Retract it from memory
258 // Now that the manager is inserted into Drools working memory, we'll wait for
259 // another rule to fire in order to continue processing. This way we can also
260 // then screen for additional ONSET and ABATED events for this RequestId.
263 } catch (Exception e) {
264 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
266 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
267 notification.setNotification(ControlLoopNotificationType.REJECTED);
268 notification.setMessage("Exception occurred: " + e.getMessage());
269 notification.setPolicyName(drools.getRule().getName());
270 notification.setPolicyScope("${policyScope}");
271 notification.setPolicyVersion("${policyVersion}");
275 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
285 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
286 * is now created. We can start processing the yaml specification via the Event Manager.
289 rule "${policyName}.EVENT.MANAGER"
291 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
292 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
293 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
294 requestId == $event.getRequestId() )
295 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
296 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
299 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
300 logger.info("{}: {}: event={} manager={} clTimer={}",
301 $params.getClosedLoopControlName(), drools.getRule().getName(),
302 $event, $manager, $clTimer);
306 // Check which event this is.
308 ControlLoopEventManager.NewEventStatus eventStatus = $manager.onNewEvent($event);
310 // Check what kind of event this is
312 if (eventStatus == NewEventStatus.SUBSEQUENT_ONSET) {
314 // We don't care about subsequent onsets
316 logger.info("{}: {}: subsequent onset",
317 $params.getClosedLoopControlName(), drools.getRule().getName());
321 if (eventStatus == NewEventStatus.SYNTAX_ERROR) {
323 // Ignore any bad syntax events
325 logger.warn("{}: {}: syntax error",
326 $params.getClosedLoopControlName(), drools.getRule().getName());
331 // We only want the initial ONSET event in memory,
332 // all the other events need to be retracted to support
333 // cleanup and avoid the other rules being fired for this event.
335 if (eventStatus != NewEventStatus.FIRST_ONSET) {
336 logger.warn("{}: {}: not first onset",
337 $params.getClosedLoopControlName(), drools.getRule().getName());
341 logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(),
342 drools.getRule().getName(), $event.getTarget());
344 // Now start seeing if we need to process this event
348 // Check if this is a Final Event
350 VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
353 if (notification != null) {
355 // Its final, but are we waiting for abatement?
357 if ($manager.getNumAbatements() > 0) {
358 logger.info("{}: {}: abatement received for {}. Closing the control loop",
359 $params.getClosedLoopControlName(), drools.getRule().getName(),
360 $event.getRequestId());
362 /// DB Write---end event processing for this RequestId()
363 $manager.commitAbatement("Event Abated","Closed");
365 notification.setFrom("policy");
366 notification.setPolicyName(drools.getRule().getName());
367 notification.setPolicyScope("${policyScope}");
368 notification.setPolicyVersion("${policyVersion}");
370 // In this case, we are done
372 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
376 Lock lock = $manager.unlockCurrentOperation();
378 logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
379 drools.getRule().getName(), lock);
383 // Retract everything from memory
385 logger.info("{}: {}: retracting onset, manager, and timer",
386 $params.getClosedLoopControlName(), drools.getRule().getName());
388 retract($manager.getOnsetEvent());
390 // don't retract manager, etc. - a clean-up rule will do that
393 // TODO - what if we get subsequent Events for this RequestId?
394 // By default, it will all start over again. May be confusing for Ruby.
395 // Or, we could track this and then subsequently ignore the events
399 // Check whether we need to wait for abatement
401 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
402 logger.info("{}: {}: waiting for abatement ..",
403 $params.getClosedLoopControlName(), drools.getRule().getName());
405 logger.info("{}: {}: no abatement expect for {}. Closing the control loop",
406 $params.getClosedLoopControlName(), drools.getRule().getName(),
407 $event.getRequestId());
409 notification.setFrom("policy");
410 notification.setPolicyName(drools.getRule().getName());
411 notification.setPolicyScope("${policyScope}");
412 notification.setPolicyVersion("${policyVersion}");
415 // In this case, we are done
417 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
421 Lock lock = $manager.unlockCurrentOperation();
423 logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
424 drools.getRule().getName(), lock);
428 // Retract everything from memory
430 logger.info("{}: {}: retracting onset, manager, and timer",
431 $params.getClosedLoopControlName(), drools.getRule().getName());
433 retract($manager.getOnsetEvent());
435 // don't retract manager, etc. - a clean-up rule will do that
440 // NOT final, so let's ask for the next operation
442 ControlLoopOperationManager operation = $manager.processControlLoop();
443 if (operation != null) {
445 // Let's ask for a lock right away
447 logger.info("{}: {}: requesting lock for operation={}",
448 $params.getClosedLoopControlName(), drools.getRule().getName(),
451 Pair<Lock,Lock> oldNew = $manager.lockCurrentOperation(
452 new LockCallbackWorkingMemory($params.getClosedLoopControlName(), drools.getWorkingMemory()));
453 if(oldNew.first() != null) {
454 logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
455 drools.getRule().getName(), oldNew.first());
456 retract(oldNew.first());
458 if(oldNew.second() != null) {
459 logger.debug("{}: {}: inserting lock={}", $params.getClosedLoopControlName(),
460 drools.getRule().getName(), oldNew.second());
461 insert(oldNew.second());
465 // insert the operation into memory
469 // insert operation timeout object
471 ControlLoopTimer opTimer = new ControlLoopTimer();
472 opTimer.setTimerType("Operation");
473 opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
474 opTimer.setRequestId($event.getRequestId().toString());
475 Integer timeout = operation.getOperationTimeout();
476 opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
481 // Probably waiting for abatement
483 logger.info("{}: {}: no operation, probably waiting for abatement",
484 $params.getClosedLoopControlName(), drools.getRule().getName());
487 } catch (Exception e) {
488 logger.warn("{}: {}: unexpected",
489 $params.getClosedLoopControlName(),
490 drools.getRule().getName(), e);
492 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
493 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
494 notification.setMessage(e.getMessage());
495 notification.setFrom("policy");
496 notification.setPolicyName(drools.getRule().getName());
497 notification.setPolicyScope("${policyScope}");
498 notification.setPolicyVersion("${policyVersion}");
500 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
504 // don't retract manager, etc. - a clean-up rule will do that
514 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCK.DENIED"
516 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
517 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
518 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
519 requestId == $event.getRequestId() )
520 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
521 onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
522 $lock : Lock (ownerKey == $event.getRequestId().toString(), isUnavailable())
525 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
526 logger.info("{}: {}: event={} manager={} operation={} lock={}",
527 $params.getClosedLoopControlName(), drools.getRule().getName(),
528 $event, $manager, $operation, $lock);
530 logger.debug("The target resource {} is already processing",
531 $event.getAai().get($event.getTarget()));
532 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
533 notification.setNotification(ControlLoopNotificationType.REJECTED);
534 notification.setMessage("The target " + $event.getAai().get($event.getTarget())
535 + " is already locked");
536 notification.setFrom("policy");
537 notification.setPolicyName(drools.getRule().getName());
538 notification.setPolicyScope("${policyScope}");
539 notification.setPolicyVersion("${policyVersion}");
541 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
545 // don't retract manager, etc. - a clean-up rule will do that
550 * Guard Permitted, let's send request to the actor.
553 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
555 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
556 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
557 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
558 requestId == $event.getRequestId() )
559 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
560 onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
561 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
562 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
565 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
566 logger.info("{}: {}: event={} manager={} operation={}",
567 $params.getClosedLoopControlName(), drools.getRule().getName(),
568 $event, $manager, $operation);
570 Object request = null;
571 boolean caughtException = false;
574 request = $operation.startOperation($event);
576 if (request != null) {
577 logger.debug("{}: {}: starting operation ..",
578 $params.getClosedLoopControlName(), drools.getRule().getName());
580 // Tell interested parties we are performing this Operation
582 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
583 notification.setNotification(ControlLoopNotificationType.OPERATION);
584 notification.setMessage($operation.getOperationMessage());
585 notification.setHistory($operation.getHistory());
586 notification.setFrom("policy");
587 notification.setPolicyName(drools.getRule().getName());
588 notification.setPolicyScope("${policyScope}");
589 notification.setPolicyVersion("${policyVersion}");
591 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
593 switch ($operation.policy.getActor()){
596 if (request instanceof Request) {
597 PolicyEngineConstants.getManager().deliver("APPC-CL", request);
599 else if (request instanceof AppcLcmDmaapWrapper) {
600 PolicyEngineConstants.getManager().deliver("APPC-LCM-READ", request);
604 // at this point the AAI named query request should have already been made,
605 // the response recieved and used
606 // in the construction of the SO Request which is stored in operationRequest
608 if(request instanceof SoRequest) {
609 // Call SO. The response will be inserted into memory once it's received
610 class mySoCallback implements SoManager.SoCallback {
611 public void onSoResponseWrapper(SoResponseWrapper wrapper) {
612 drools.getWorkingMemory().insert(wrapper);
615 SoActorServiceProvider.sendRequest($event.getRequestId().toString(),
618 PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
619 PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
620 PolicyEngineConstants.getManager().getEnvironmentProperty("so.password"));
624 if (request instanceof VfcRequest) {
626 class myVfcCallback implements VfcManager.VfcCallback {
628 public void onResponse(VfcResponse responseError) {
629 drools.getWorkingMemory().insert(responseError);
633 Thread t = new Thread(new VfcManager(new myVfcCallback(),
635 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.url"),
636 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
637 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password")));
643 if (request instanceof SdncRequest) {
645 class mySdncCallback implements SdncManager.SdncCallback {
646 public void onCallback(SdncResponse response) {
647 drools.getWorkingMemory().insert(response);
651 Thread t = new Thread(new SdncManager(new mySdncCallback(),
652 (SdncRequest)request,
653 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
654 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
655 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
660 if (request instanceof PciRequestWrapper) {
661 PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
667 if(request instanceof ExecutionServiceInput) {
669 // Instantiate cds actor, service manager and grpc properties
671 CdsActorServiceProvider cdsActor = new CdsActorServiceProvider();
672 CdsActorServiceProvider.CdsActorServiceManager cdsActorServiceManager = cdsActor.new CdsActorServiceManager();
674 CdsServerProperties props = new CdsServerProperties();
675 props.setHost(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcHost"));
676 props.setPort(Integer.parseInt(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcPort")));
677 props.setUsername(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcUsername"));
678 props.setPassword(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcPassword"));
679 props.setTimeout(Integer.parseInt(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcTimeout")));
681 // Send cds grpc request
682 try (CdsProcessorGrpcClient client = new CdsProcessorGrpcClient(cdsActorServiceManager, props)) {
683 CdsResponse response =
684 cdsActorServiceManager.sendRequestToCds(client, props, (ExecutionServiceInput) request);
685 logger.info("CDS response: {}", response);
695 // What happens if its null?
697 logger.warn("{}: {}: unexpected null operation request",
698 $params.getClosedLoopControlName(),
699 drools.getRule().getName());
700 if ("SO".equals($operation.policy.getActor())) {
703 modify($manager) {finishOperation($operation)};
705 else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
708 modify($manager) {finishOperation($operation)};
710 else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
713 modify($manager) {finishOperation($operation)};
717 } catch (Exception e) {
718 String msg = e.getMessage();
719 logger.warn("{}: {}: operation={}: AAI failure: {}",
720 $params.getClosedLoopControlName(), drools.getRule().getName(),
722 $operation.setOperationHasException(msg);
724 if(request != null) {
726 // Create a notification for it ("DB Write - end operation")
728 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
729 notification.setFrom("policy");
730 notification.setPolicyName(drools.getRule().getName());
731 notification.setPolicyScope("${policyScope}");
732 notification.setPolicyVersion("${policyVersion}");
733 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
734 notification.setMessage($operation.getOperationHistory());
735 notification.setHistory($operation.getHistory());
737 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
742 caughtException = true;
745 // Having the modify statement in the catch clause doesn't work for whatever reason
746 if (caughtException) {
747 modify($manager) {finishOperation($operation)};
754 * We were able to acquire a lock so now let's ask Xacml Guard whether
755 * we are allowed to proceed with the request to the actor.
758 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
760 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
761 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
762 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
763 requestId == $event.getRequestId() )
764 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
765 onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
766 $lock : Lock (ownerKey == $event.getRequestId().toString(), isActive())
769 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
770 logger.info("{}: {}: event={} manager={} operation={} lock={}",
771 $params.getClosedLoopControlName(), drools.getRule().getName(),
772 $event, $manager, $operation, $lock);
775 // Sending notification that we are about to query Guard ("DB write - start operation")
777 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
778 notification.setNotification(ControlLoopNotificationType.OPERATION);
779 notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
780 + $operation.policy.getRecipe());
781 notification.setHistory($operation.getHistory());
782 notification.setFrom("policy");
783 notification.setPolicyName(drools.getRule().getName());
784 notification.setPolicyScope("${policyScope}");
785 notification.setPolicyVersion("${policyVersion}");
787 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
790 // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
791 // just change guardEnabled to false.
793 // In order to use REST XACML, provide a URL instead of "" as a second argument
794 // to the CallGuardTask() and set the first argument to null
795 // (instead of XacmlPdpEngine).
798 // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
799 boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("guard.disabled"));
800 boolean cqEnabled = "true".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("aai.customQuery"));
804 Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
805 drools.getWorkingMemory(),
806 $event.getClosedLoopControlName(),
807 $operation.policy.getActor().toString(),
808 $operation.policy.getRecipe(),
809 $operation.getTargetEntity(),
810 $event.getRequestId().toString(),
813 AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
814 return(resp == null ? null : resp.countVfModules());
817 AaiCqResponse resp_cq = $manager.getCqResponse($event);
818 if (resp_cq == null){
821 String custId = $operation.policy.getTarget().getModelCustomizationId();
822 String invId = $operation.policy.getTarget().getModelInvariantId();
823 String verId = $operation.policy.getTarget().getModelVersionId();
824 return resp_cq.getVfModuleCount(custId, invId, verId);
826 } catch (Exception e){
827 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
835 insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
841 // This rule will be triggered when a thread talking to the XACML Guard inserts a
842 // guardResponse object into the working memory
844 rule "${policyName}.GUARD.RESPONSE"
846 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
847 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
848 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
849 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
850 requestId == $event.getRequestId() )
851 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
852 onset.getRequestId() == $event.getRequestId() )
853 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
854 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
855 $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
858 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
859 logger.info("{}: {}: event={} manager={} operation={} opTimer={} guardResponse={}",
860 $params.getClosedLoopControlName(), drools.getRule().getName(),
861 $event, $manager, $operation, $opTimer, $guardResponse);
864 //we will permit the operation if there was no Guard for it
865 if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
866 $guardResponse.setResult("Permit");
870 // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
872 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
873 notification.setNotification(ControlLoopNotificationType.OPERATION);
874 notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
875 + " is " + $guardResponse.getResult());
876 notification.setHistory($operation.getHistory());
877 notification.setFrom("policy");
878 notification.setPolicyName(drools.getRule().getName());
879 notification.setPolicyScope("${policyScope}");
880 notification.setPolicyVersion("${policyVersion}");
882 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
884 if("Permit".equalsIgnoreCase($guardResponse.getResult())){
886 modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
889 //This is the Deny case
890 $operation.startOperation($event);
891 $operation.setOperationHasGuardDeny();
894 modify($manager) {finishOperation($operation)};
897 retract($guardResponse);
903 * This rule responds to APPC Response Events
905 * I would have like to be consistent and write the Response like this:
906 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
908 * However, no compile error was given. But a runtime error was given. I think
909 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
912 rule "${policyName}.APPC.RESPONSE"
914 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
915 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
916 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
917 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
918 requestId == $event.getRequestId() )
919 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
920 onset.getRequestId() == $event.getRequestId() )
921 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
922 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
923 $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
926 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
927 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
928 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
929 $params.getClosedLoopControlName(), drools.getRule().getName(),
930 $event, $manager, $operation, $opTimer, $response);
932 // Get the result of the operation
934 PolicyResult policyResult = $operation.onResponse($response);
935 if (policyResult != null) {
936 logger.debug("{}: {}: operation finished - result={}",
937 $params.getClosedLoopControlName(), drools.getRule().getName(),
940 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
942 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
943 notification.setFrom("policy");
944 notification.setPolicyName(drools.getRule().getName());
945 notification.setPolicyScope("${policyScope}");
946 notification.setPolicyVersion("${policyVersion}");
947 notification.setMessage($operation.getOperationHistory());
948 notification.setHistory($operation.getHistory());
949 if (policyResult.equals(PolicyResult.SUCCESS)) {
950 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
952 // Let interested parties know
954 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
956 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
958 // Let interested parties know
960 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
963 // Ensure the operation is complete
965 if ($operation.isOperationComplete() == true) {
967 // It is complete, remove it from memory
971 // We must also retract the timer object
972 // NOTE: We could write a Rule to do this
976 // Complete the operation
978 modify($manager) {finishOperation($operation)};
981 // Just doing this will kick off the LOCKED rule again
983 modify($operation) {};
987 // Its not finished yet (i.e. expecting more Response objects)
989 // Or possibly it is a leftover response that we timed the request out previously
993 // We are going to retract these objects from memory
1000 * The problem with Responses is that they don't have a controlLoopControlName
1001 * field in them, so the only way to attach them is via RequestId. If we have multiple
1002 * control loop .drl's loaded in the same container, we need to be sure the cleanup
1003 * rules don't remove Responses for other control loops.
1006 rule "${policyName}.APPC.RESPONSE.CLEANUP"
1008 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1009 $response : Response($id : getCommonHeader().RequestId )
1010 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1013 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1014 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1015 logger.debug("{}: {}: orphan appc response={}",
1016 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1026 * This rule responds to APPC Response Events using the new LCM interface provided by appc
1029 rule "${policyName}.APPC.LCM.RESPONSE"
1031 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1032 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1033 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1034 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1035 requestId == $event.getRequestId() )
1036 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1037 onset.getRequestId() == $event.getRequestId() )
1038 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1039 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1040 $response : AppcLcmDmaapWrapper( getBody().getOutput().getCommonHeader().getRequestId() == $event.getRequestId() )
1043 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1044 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1045 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1046 $params.getClosedLoopControlName(), drools.getRule().getName(),
1047 $event, $manager, $operation, $operation, $opTimer, $response);
1050 // Get the result of the operation
1052 PolicyResult policyResult = $operation.onResponse($response);
1053 if (policyResult != null) {
1054 logger.debug("{}: {}: operation finished - result={}",
1055 $params.getClosedLoopControlName(), drools.getRule().getName(),
1059 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1061 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1062 notification.setFrom("policy");
1063 notification.setPolicyName(drools.getRule().getName());
1064 notification.setPolicyScope("${policyScope}");
1065 notification.setPolicyVersion("${policyVersion}");
1066 notification.setMessage($operation.getOperationHistory());
1067 notification.setHistory($operation.getHistory());
1068 if (policyResult.equals(PolicyResult.SUCCESS)) {
1069 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1071 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1073 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1075 // Ensure the operation is complete
1077 if ($operation.isOperationComplete() == true) {
1079 // It is complete, remove it from memory
1081 retract($operation);
1083 // We must also retract the timer object
1084 // NOTE: We could write a Rule to do this
1088 // Complete the operation
1090 modify($manager) {finishOperation($operation)};
1093 // Just doing this will kick off the LOCKED rule again
1095 modify($operation) {};
1099 // Its not finished yet (i.e. expecting more Response objects)
1101 // Or possibly it is a leftover response that we timed the request out previously
1105 // We are going to retract these objects from memory
1112 * Clean Up any lingering LCM reponses
1115 rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
1117 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1118 $response : AppcLcmDmaapWrapper($id : getBody().getOutput().getCommonHeader().getRequestId() )
1119 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1122 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1123 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1124 logger.debug("{}: {}: orphan appc response={}",
1125 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1134 * This rule responds to SDNR Response Events using the new interface provided by SDNR
1137 rule "${policyName}.SDNR.RESPONSE"
1139 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1140 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1141 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1142 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1143 requestId == $event.getRequestId() )
1144 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1145 onset.getRequestId() == $event.getRequestId() )
1146 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1147 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1148 $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1151 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1152 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1153 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1154 $params.getClosedLoopControlName(), drools.getRule().getName(),
1155 $event, $manager, $operation, $operation, $opTimer, $response);
1158 // Get the result of the operation
1160 PolicyResult policyResult = $operation.onResponse($response);
1161 if (policyResult != null) {
1162 logger.debug("{}: {}: operation finished - result={}",
1163 $params.getClosedLoopControlName(), drools.getRule().getName(),
1167 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1169 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1170 notification.setFrom("policy");
1171 notification.setPolicyName(drools.getRule().getName());
1172 notification.setPolicyScope("${policyScope}");
1173 notification.setPolicyVersion("${policyVersion}");
1174 notification.setMessage($operation.getOperationHistory());
1175 notification.setHistory($operation.getHistory());
1176 if (policyResult.equals(PolicyResult.SUCCESS)) {
1177 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1179 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1181 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1183 // Ensure the operation is complete
1185 if ($operation.isOperationComplete()) {
1187 // It is complete, remove it from memory
1189 retract($operation);
1191 // We must also retract the timer object
1192 // NOTE: We could write a Rule to do this
1196 // Complete the operation
1198 modify($manager) {finishOperation($operation)};
1201 // Just doing this will kick off the LOCKED rule again
1203 modify($operation) {};
1207 // Its not finished yet (i.e. expecting more Response objects)
1209 // Or possibly it is a leftover response that we timed the request out previously
1213 // We are going to retract these objects from memory
1220 * Clean Up any lingering SDNR reponses
1223 rule "${policyName}.SDNR.RESPONSE.CLEANUP"
1225 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1226 $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1227 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1230 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1231 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1232 logger.debug("{}: {}: orphan SDNR response={}",
1233 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
1242 * This rule responds to SO Response Events
1245 rule "${policyName}.SO.RESPONSE"
1247 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1248 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1249 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1250 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1251 requestId == $event.getRequestId() )
1252 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1253 onset.getRequestId() == $event.getRequestId() )
1254 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1255 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1256 $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
1259 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1260 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1261 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1262 $params.getClosedLoopControlName(), drools.getRule().getName(),
1263 $event, $manager, $operation, $operation, $opTimer, $response);
1265 // Get the result of the operation
1267 PolicyResult policyResult = $operation.onResponse($response);
1268 if (policyResult != null) {
1269 logger.debug("{}: {}: operation finished - result={}",
1270 $params.getClosedLoopControlName(), drools.getRule().getName(),
1274 // This Operation has completed, construct a notification showing our results
1276 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1277 notification.setFrom("policy");
1278 notification.setPolicyName(drools.getRule().getName());
1279 notification.setPolicyScope("${policyScope}");
1280 notification.setPolicyVersion("${policyVersion}");
1281 notification.setMessage($operation.getOperationHistory());
1282 notification.setHistory($operation.getHistory());
1283 if (policyResult.equals(PolicyResult.SUCCESS)) {
1284 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1286 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1289 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1291 // Ensure the operation is complete
1293 if ($operation.isOperationComplete() == true) {
1295 // It is complete, remove it from memory
1297 retract($operation);
1299 // We must also retract the timer object
1300 // NOTE: We could write a Rule to do this
1304 // Complete the operation
1306 modify($manager) {finishOperation($operation)};
1309 // Just doing this will kick off the LOCKED rule again
1311 modify($operation) {};
1315 // Its not finished yet (i.e. expecting more Response objects)
1317 // Or possibly it is a leftover response that we timed the request out previously
1321 // We are going to retract these objects from memory
1329 * This rule responds to VFC Response Events
1332 rule "${policyName}.VFC.RESPONSE"
1334 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1335 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1336 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1337 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1338 requestId == $event.getRequestId() )
1339 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1340 onset.getRequestId() == $event.getRequestId() )
1341 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1342 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1343 $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1345 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1346 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1347 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1348 $params.getClosedLoopControlName(), drools.getRule().getName(),
1349 $event, $manager, $operation, $operation, $opTimer, $response);
1351 // Get the result of the operation
1353 PolicyResult policyResult = $operation.onResponse($response);
1354 if (policyResult != null) {
1356 // This Operation has completed, construct a notification showing our results
1358 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1359 notification.setFrom("policy");
1360 notification.setPolicyName(drools.getRule().getName());
1361 notification.setPolicyScope("${policyScope}");
1362 notification.setPolicyVersion("${policyVersion}");
1363 notification.setMessage($operation.getOperationHistory());
1364 notification.setHistory($operation.getHistory());
1366 // Ensure the operation is complete
1368 if ($operation.isOperationComplete() == true) {
1370 // It is complete, remove it from memory
1372 retract($operation);
1374 // We must also retract the timer object
1375 // NOTE: We could write a Rule to do this
1379 // Complete the operation
1381 modify($manager) {finishOperation($operation)};
1384 // Just doing this will kick off the LOCKED rule again
1386 modify($operation) {};
1390 // Its not finished yet (i.e. expecting more Response objects)
1392 // Or possibly it is a leftover response that we timed the request out previously
1396 // We are going to retract these objects from memory
1404 * This rule responds to SDNC Response Events
1408 rule "${policyName}.SDNC.RESPONSE"
1410 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1411 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1412 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1413 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1414 requestId == $event.getRequestId() )
1415 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1416 onset.getRequestId() == $event.getRequestId() )
1417 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1418 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1419 $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1421 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1422 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1423 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1424 $params.getClosedLoopControlName(), drools.getRule().getName(),
1425 $event, $manager, $operation, $operation, $opTimer, $response);
1427 // Get the result of the operation
1429 PolicyResult policyResult = $operation.onResponse($response);
1430 if (policyResult != null) {
1432 // This Operation has completed, construct a notification showing our results
1434 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1435 notification.setFrom("policy");
1436 notification.setPolicyName(drools.getRule().getName());
1437 notification.setPolicyScope("${policyScope}");
1438 notification.setPolicyVersion("${policyVersion}");
1439 notification.setMessage($operation.getOperationHistory());
1440 notification.setHistory($operation.getHistory());
1442 // Ensure the operation is complete
1444 if ($operation.isOperationComplete()) {
1446 // It is complete, remove it from memory
1448 retract($operation);
1450 // We must also retract the timer object
1451 // NOTE: We could write a Rule to do this
1455 // Complete the operation
1457 modify($manager) {finishOperation($operation)};
1460 // Just doing this will kick off the LOCKED rule again
1462 modify($operation) {};
1466 // Its not finished yet (i.e. expecting more Response objects)
1468 // Or possibly it is a leftover response that we timed the request out previously
1472 // We are going to retract these objects from memory
1480 * This rule responds to CDS Response Events
1482 rule "${policyName}.CDS.RESPONSE"
1484 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1485 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1486 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1487 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1488 requestId == $event.getRequestId() )
1489 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1490 onset.getRequestId() == $event.getRequestId() )
1491 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1492 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1493 $response : CdsResponse( requestId == $event.getRequestId().toString() )
1497 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1498 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1499 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1500 $params.getClosedLoopControlName(), drools.getRule().getName(),
1501 $event, $manager, $operation, $operation, $opTimer, $response);
1503 // Get the result of the operation
1504 PolicyResult policyResult = $operation.onResponse($response);
1506 if (policyResult != null) {
1507 logger.debug("{}: {}: operation finished - result={}",
1508 $params.getClosedLoopControlName(), drools.getRule().getName(),
1511 // The operation has completed, construct a notification showing our results
1512 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1513 notification.setFrom("policy");
1514 notification.setPolicyName(drools.getRule().getName());
1515 notification.setPolicyScope("${policyScope}");
1516 notification.setPolicyVersion("${policyVersion}");
1517 notification.setMessage($operation.getOperationHistory());
1518 notification.setHistory($operation.getHistory());
1519 notification.setNotification(
1520 ($response != null && CdsActorConstants.SUCCESS.equals($response.getStatus()))
1521 ? ControlLoopNotificationType.OPERATION_SUCCESS : ControlLoopNotificationType.OPERATION_FAILURE);
1523 // Send the notification
1524 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1526 // Ensure the operation is complete
1527 if ($operation.isOperationComplete()) {
1529 // It is complete, remove it from memory
1530 retract($operation);
1532 // We must also retract the timer object
1533 // NOTE: We could write a Rule to do this
1536 // Complete the operation
1537 modify($manager) {finishOperation($operation)};
1540 // Just doing this will kick off the LOCKED rule again
1541 modify($operation) {};
1544 // Its not finished yet (i.e. expecting more Response objects)
1545 // Or possibly it is a leftover response that we timed the request out previously
1547 "policyResult is null"
1548 + "\nIt's not finished yet (i.e. expecting more Response objects)"
1549 + "\nOr possibly it is a leftover response that we timed the request out previously");
1552 // We are going to retract these objects from memory
1559 * This manages a single timer.
1560 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1563 rule "${policyName}.TIMER.FIRED"
1564 timer (expr: $timeout)
1566 $timer : ControlLoopTimer($timeout : delay, !expired)
1568 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1569 logger.info("This is ${policyName}.TIMER.FIRED");
1570 modify($timer){setExpired(true)};
1575 * This is the timer that manages the timeout for an individual operation.
1578 rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT"
1580 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1581 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1582 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1583 requestId == $event.getRequestId() )
1584 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1585 onset.getRequestId() == $event.getRequestId() )
1586 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1587 requestId == $event.getRequestId().toString(), expired, timerType == "Operation" )
1590 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1591 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1592 logger.debug("{}: {}: event={} manager={} operation={} opTimer={}",
1593 $params.getClosedLoopControlName(), drools.getRule().getName(),
1594 $event, $manager, $operation, $operation, $opTimer);
1597 // Tell it it has timed out
1599 $operation.setOperationHasTimedOut();
1601 // Create a notification for it ("DB Write - end operation")
1603 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1604 notification.setFrom("policy");
1605 notification.setPolicyName(drools.getRule().getName());
1606 notification.setPolicyScope("${policyScope}");
1607 notification.setPolicyVersion("${policyVersion}");
1608 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1609 notification.setMessage($operation.getOperationHistory());
1610 notification.setHistory($operation.getHistory());
1612 // Let interested parties know
1614 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1616 // Get rid of the timer
1620 // Ensure the operation is complete
1622 if ($operation.isOperationComplete() == true) {
1624 // It is complete, remove it from memory
1626 retract($operation);
1628 // Complete the operation
1630 modify($manager) {finishOperation($operation)};
1633 // Just doing this will kick off the LOCKED rule again
1635 modify($operation) {};
1641 * This is the timer that manages the overall control loop timeout.
1644 rule "${policyName}.EVENT.MANAGER.TIMEOUT"
1646 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1647 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1648 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1649 requestId == $event.getRequestId() )
1650 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1651 requestId == $event.getRequestId().toString(), expired, timerType == "ClosedLoop" )
1654 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1655 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1657 logger.debug("{}: {}: event={}",
1658 $params.getClosedLoopControlName(), drools.getRule().getName(),
1661 // Tell the Event Manager it has timed out
1663 VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1664 if (notification != null) {
1665 notification.setFrom("policy");
1666 notification.setPolicyName(drools.getRule().getName());
1667 notification.setPolicyScope("${policyScope}");
1668 notification.setPolicyVersion("${policyVersion}");
1670 // Let interested parties know
1672 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1675 // Retract the event
1682 * This rule cleans up the manager and other objects after an event has
1686 rule "${policyName}.EVENT.MANAGER.CLEANUP"
1688 $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
1689 $operations : LinkedList()
1690 from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
1691 onset.getRequestId() == $requestId ) )
1692 $timers : LinkedList()
1693 from collect( ControlLoopTimer( closedLoopControlName == $clName,
1694 requestId == $requestId.toString() ) )
1695 not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1698 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1699 logger.info("{}: {}", $clName, drools.getRule().getName());
1701 logger.debug("{}: {}: manager={} timers={} operations={}",
1702 $clName, drools.getRule().getName(),
1703 $manager, $timers.size(), $operations.size());
1706 // Retract lock by invoking unlock()
1708 Lock lock = $manager.unlockCurrentOperation();
1714 // Retract EVERYTHING
1719 for(Object manager: $operations) {
1720 retract((ControlLoopOperationManager) manager);
1722 for(Object timer: $timers) {
1723 retract((ControlLoopTimer) timer);
1729 * This rule will clean up any rogue onsets where there is no
1730 * ControlLoopParams object corresponding to the onset event.
1733 rule "${policyName}.EVENT.CLEANUP"
1735 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1736 not ( Params( getClosedLoopControlName() == $clName) )
1739 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1740 logger.info("{}: {}", $clName, drools.getRule().getName());
1741 logger.debug("{}: {}: orphan onset event={}",
1742 $clName, drools.getRule().getName(), $event);
1748 * Creates a cleaner for every Params object.
1749 * This has a higher salience so that it is fired before PARAMS.FINISHED in ANY policy.
1751 rule "${policyName}.PARAMS.CLEANING"
1755 ParamsInitCleaner( )
1758 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1759 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1760 $params.getControlLoopYaml());
1762 ParamsCleaner cleaner = new ParamsCleaner();
1763 cleaner.setClosedLoopControlName($params.getClosedLoopControlName());
1764 cleaner.setControlLoopYaml($params.getControlLoopYaml());
1769 * Finished creating cleaner objects, so remove the trigger.
1770 * This has a higher salience so that it is fired before processing any events.
1772 rule "${policyName}.PARAMS.FINISHED"
1775 $initCleaner: ParamsInitCleaner( )
1778 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1779 logger.info("{}: {}", $initCleaner.getClosedLoopControlName(), drools.getRule().getName());
1781 retract($initCleaner);
1785 * Identifies Params objects that are still active, removing their associated cleaners.
1786 * This should only leave one active Params object for each policy.
1787 * This has a higher salience so that it is fired before PARAMS.DELETE in ANY policy.
1789 rule "${policyName}.PARAMS.ACTIVE"
1792 $params: Params( getClosedLoopControlName() == "${closedLoopControlName}",
1793 getControlLoopYaml() == "${controlLoopYaml}" )
1794 $cleaner: ParamsCleaner( getClosedLoopControlName() == "${closedLoopControlName}",
1795 getControlLoopYaml() == "${controlLoopYaml}" )
1798 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1799 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1800 $params.getControlLoopYaml());
1806 * Delete Params objects that are not active (i.e., those that still have an associated
1808 * This has a higher salience so that it is fired before PARAMS.CLEANED in ANY policy.
1810 rule "${policyName}.PARAMS.DELETE"
1814 $cleaner: ParamsCleaner( getClosedLoopControlName() == $params.getClosedLoopControlName(),
1815 getControlLoopYaml() == $params.getControlLoopYaml() )
1818 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1819 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
1820 $params.getControlLoopYaml());
1826 * Finished clean-up, so delete the cleaner objects.
1827 * This has a higher salience so that it is fired before processing any events.
1829 rule "${policyName}.PARAMS.CLEANED"
1832 $cleaner: ParamsCleaner( )
1835 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1836 logger.info("{}: {} : YAML=[{}]", $cleaner.getClosedLoopControlName(), drools.getRule().getName(),
1837 $cleaner.getControlLoopYaml());