diff options
Diffstat (limited to 'controlloop/templates/template.demo/src/main/resources')
6 files changed, 2872 insertions, 0 deletions
diff --git a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_1707_xacml_guard.drl b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_1707_xacml_guard.drl new file mode 100644 index 000000000..330f41b56 --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_1707_xacml_guard.drl @@ -0,0 +1,917 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package com.att.ecomp.policy.controlloop; + +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.ControlLoopLogger; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager; +import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS; +import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager; +import org.onap.policy.appc.Request; +import org.onap.policy.appc.Response; +import org.onap.policy.appc.CommonHeader; +import org.onap.policy.guard.PolicyGuard; +import org.onap.policy.guard.PolicyGuard.LockResult; +import org.onap.policy.guard.TargetLock; +import org.onap.policy.guard.GuardResult; +import org.onap.policy.guard.PolicyGuardRequest; +import org.onap.policy.guard.PolicyGuardResponse; +import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.std.annotations.RequestParser; +import org.onap.policy.guard.PolicyGuardXacmlHelper; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.Policy; +import java.net.URLDecoder; +import org.eclipse.persistence.exceptions.DatabaseException; + +// +// REPLACE THESE WITH PRODUCTION VERSIONS +// +import org.onap.policy.controlloop.ControlLoopLogger; +import org.onap.policy.drools.PolicyEngine; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +global ControlLoopLogger Logger; +global PolicyEngine Engine; +global PDPEngine XacmlPdpEngine; + +import java.time.Instant; +import java.util.LinkedList; +import java.util.Iterator; + +declare Params + closedLoopControlName : String + controlLoopYaml : String +end + + +declare OperationTimer + closedLoopControlName : String + requestID : String + delay : String +end + +declare ControlLoopTimer + closedLoopControlName : String + requestID : String + delay : String +end + + +/* +* +* Called once and only once to insert the parameters into working memory for this Closed Loop policy. +* +*/ +rule "${policyName}.SETUP" + when + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Params params = new Params(); + params.setClosedLoopControlName("${closedLoopControlName}"); + params.setControlLoopYaml("${controlLoopYaml}"); + insert(params); + Logger.metrics("Inserted " + params); + Logger.info("------------------------------------------------------------------------------------------------"); + +end + +/* +* +* This rule responds to DCAE Events where there is no manager yet. Either it is +* the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled) +* +*/ +rule "${policyName}.EVENT" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + not ( ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) ) + then + try { + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + // + // Check the event, because we need it to not be null when + // we create the ControlLoopEventManager. The ControlLoopEventManager + // will do extra syntax checking as well check if the closed loop is disabled. + // + if ($event.requestID == null) { + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Missing requestID"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } else { + // + // Create an EventManager + // + ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(), $event.requestID); + // + // Determine if EventManager can actively process the event (i.e. syntax, is_closed_loop_disabled checks etc.) + // + VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event); + notification.from = "pdp-0001-controller=controlloop"; // Engine.getInstanceName() + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Are we actively pursuing this event? + // + if (notification.notification == ControlLoopNotificationType.ACTIVE) { + // + // Insert Event Manager into memory, this will now kick off processing. + // + insert(manager); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Setup the Overall Control Loop timer + // + ControlLoopTimer clTimer = new ControlLoopTimer(); + clTimer.setClosedLoopControlName($event.closedLoopControlName); + clTimer.setRequestID($event.requestID.toString()); + clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s"); + // + // Insert it + // + insert(clTimer); + } else { + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } + // + // Now that the manager is inserted into Drools working memory, we'll wait for + // another rule to fire in order to continue processing. This way we can also + // then screen for additional ONSET and ABATED events for this RequestID. + // + } + } catch (Exception e) { + e.printStackTrace(); + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract the event + // + retract($event); + } +end + +/* +* +* This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager +* is now created. We can start processing the yaml specification via the Event Manager. +* +*/ +rule "${policyName}.EVENT.MANAGER" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($clTimer); + // + // Check which event this is. + // + ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event); + Logger.info("Event status is " + eventStatus); + // + // Check what kind of event this is + // + if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) { + // + // We don't care about subsequent onsets + // + Logger.info("Retracting Subsequent Onset " + $event); + retract($event); + return; + } + if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) { + // + // Ignore any bad syntax events + // + Logger.info("Retracting Bad Syntax Event " + $event); + retract($event); + return; + } + // + // We only want the initial ONSET event in memory, + // all the other events need to be retracted to support + // cleanup and avoid the other rules being fired for this event. + // + if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) { + Logger.info("Retracting Event " + $event); + retract($event); + } + Logger.info("Checking due to new event " + $event.target); + // + // Now start seeing if we need to process this event + // + try { + // + // Check if this is a Final Event + // + VirtualControlLoopNotification notification = $manager.isControlLoopFinal(); + + + if (notification != null) { + // + // Its final, but are we waiting for abatement? + // + if ($manager.getNumAbatements() > 0) { + Logger.info("Abatement received, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + // + // TODO - what if we get subsequent Events for this RequestID? + // By default, it will all start over again. May be confusing for Ruby. + // Or, we could track this and then subsequently ignore the events + // + } else { + // + // Check whether we need to wait for abatement + // + if ($manager.getProcessor().getControlLoop().abatement == true && notification.notification == ControlLoopNotificationType.FINAL_SUCCESS) { + Logger.info("Waiting for abatement."); + } else { + Logger.info("No abatement is promised to come, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + } + } + } else { + // + // NOT final, so let's ask for the next operation + // + ControlLoopOperationManager operation = $manager.processControlLoop(); + if (operation != null) { + Logger.info("starting a new operation" + operation); + // + // insert into memory + // + insert(operation); + // + // insert operation timeout object + // + OperationTimer opTimer = new OperationTimer(); + opTimer.setClosedLoopControlName($event.closedLoopControlName); + opTimer.setRequestID($event.requestID.toString()); + opTimer.setDelay(operation.getOperationTimeout().toString() + "s"); + insert(opTimer); + + // + // Let's ask for a lock right away + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("manager returned lock " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } + } else { + // + // Probably waiting for abatement + // + } + } + } catch (Exception e) { + e.printStackTrace(); + /* + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // TODO should we abort if we get an exception? + // + */ + } + +end + + + +/* +* +* +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.NOT_LOCKED.TIMEOUT" + timer (int: 5s 5s) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + not ( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + // + // Need to ask for a Lock + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("Lock acquired: " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } +end + +/* +* +* Guard Permitted, let's send request to the actor. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "Permit" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + + + Object request = $operation.getOperationRequest(); + + if (request != null) { + Logger.info("Starting operation"); + // + // Tell interested parties we are performing this Operation + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage(); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + switch ($operation.policy.actor){ + + case "APPC": + + if (request instanceof Request) { + Engine.deliver("UEB", "APPC-CL", request); + } + case "SDNR": + default: + } + + + } else { + // + // What happens if its null? + // + } +end + + +/* +* +* We were able to acquire a lock so now let's ask Xacml Guard whether we are allowed to proceed with the request to the actor. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "NONE" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + + + + + // + // We are starting the operation but the actor won't be contacted until Guard is queried and permitted. + // + $operation.startOperation($event); + + // + // Sending notification that we are about to query Guard ("DB write - start operation") + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage(); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + // + // Now send Guard Request to XACML Guard. In order to bypass the call to Guard, just change guardEnabled to false. + // + // In order to use REST XACML, provide a URL instead of "" as a second argument o the CallGuardTask() and set the first + // argument to null (instead of XacmlPdpEngine). + // + boolean guardEnabled = true; + + if(guardEnabled){ + + Thread t = new Thread(new org.onap.policy.guard.CallGuardTask( + XacmlPdpEngine, + "", + drools.getWorkingMemory(), + $operation.policy.actor.toString(), + $operation.policy.recipe, + $manager.getTargetInstance($operation.policy), + //$event.target, + $event.requestID.toString() + )); + t.start(); + } + else{ + insert(new PolicyGuardResponse("Permit", $event.requestID, $operation.policy.recipe)); + } + + + + +end + +// +//This rule will be triggered when a thread talking to the XACML Guard inserts a guardResponse object into the working memory +// +rule "${policyName}.GUARD.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $lock : TargetLock (requestID == $event.requestID) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $guardResponse : PolicyGuardResponse(requestID == $event.requestID, $operation.policy.recipe == operation) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($operation); + Logger.metrics($lock); + Logger.metrics($guardResponse); + + + //we will permit the operation if there was no Guard for it + if($guardResponse.result == "Indeterminate"){ + $guardResponse.result = "Permit"; + } + + // + // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny") + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage($guardResponse.result); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + + + if($guardResponse.result == "Permit"){ + + modify($operation){setGuardApprovalStatus($guardResponse.result)}; + } + else { + //This is the Deny case + $operation.setOperationHasGuardDeny(); + retract($opTimer); + retract($operation); + modify($manager) {finishOperation($operation)}; + } + + retract($guardResponse); + +end + + + + +/* +* +* This rule responds to APPC Response Events +* +* I would have like to be consistent and write the Response like this: +* $response : Response( CommonHeader.RequestID == $onset.requestID ) +* +* However, no compile error was given. But a runtime error was given. I think +* because drools is confused between the classname CommonHeader vs the property CommonHeader. +* +*/ +rule "${policyName}.APPC.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $lock : TargetLock (requestID == $event.requestID) + $response : Response( getCommonHeader().RequestID == $event.requestID ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + Logger.metrics($response); + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + Logger.info("operation finished with result: " + policyResult); + // + // This Operation has completed, construct a notification showing our results. (DB write - end operation) + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } else { + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // We must also retract the timer object + // NOTE: We could write a Rule to do this + // + retract($opTimer); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } + } else { + // + // Its not finished yet (i.e. expecting more Response objects) + // + // Or possibly it is a leftover response that we timed the request out previously + // + } + // + // We are going to retract these objects from memory + // + retract($response); +end + +/* +* +* The problem with Responses is that they don't have a controlLoopControlName +* field in them, so the only way to attach them is via RequestID. If we have multiple +* control loop .drl's loaded in the same container, we need to be sure the cleanup +* rules don't remove Responses for other control loops. +* +*/ +rule "${policyName}.APPC.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : Response($id : getCommonHeader().RequestID ) + not ( VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + // + // Retract it + // + retract($response); +end +/* +* +* This is the timer that manages the timeout for an individual operation. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + // + // Tell it its timed out + // + $operation.setOperationHasTimedOut(); + // + // Create a notification for it ("DB Write - end operation") + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Get rid of the timer + // + retract($opTimer); + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } +end + +/* +* +* This is the timer that manages the overall control loop timeout. +* +*/ +rule "${policyName}.EVENT.MANAGER.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $operations : LinkedList() + from collect( ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) ) + $opTimers : LinkedList() + from collect( OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) ) + $locks : LinkedList() + from collect( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($clTimer); + if ($operations == null) { + Logger.info("no operations found"); + } else { + Logger.info("found " + $operations.size() + " operations"); + } + // + // Tell the Event Manager it has timed out + // + VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut(); + if (notification != null) { + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Retract EVERYTHING + // + retract($event); + retract($manager); + retract($clTimer); + if ($operations != null && $operations.size() > 0) { + Iterator<ControlLoopOperationManager> iter = $operations.iterator(); + while (iter.hasNext()) { + ControlLoopOperationManager manager = iter.next(); + retract(manager); + } + } + if ($opTimers != null && $opTimers.size() > 0) { + Iterator<OperationTimer> iter = $opTimers.iterator(); + while (iter.hasNext()) { + OperationTimer opTimer = iter.next(); + retract(opTimer); + } + } + if ($locks != null && $locks.size() > 0) { + Iterator<TargetLock> iter = $locks.iterator(); + while (iter.hasNext()) { + TargetLock lock = iter.next(); + // + // Ensure we release the lock + // + PolicyGuard.unlockTarget(lock); + // + // + // + retract(lock); + } + } +end diff --git a/controlloop/templates/template.demo/src/main/resources/blacklist_template.xml b/controlloop/templates/template.demo/src/main/resources/blacklist_template.xml new file mode 100644 index 000000000..560fa57f1 --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/blacklist_template.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="urn:com:att:xacml:policy:id:25e12b06-11d5-4895-b2a2-6f6c594de069" Version="1" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny"> + <Description>Policy for frequency limiter.</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${actor}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="urn:oasis:names:tc:xacml:1.0:actor:actor-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${recipe}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" AttributeId="urn:oasis:names:tc:xacml:1.0:operation:operation-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Rule RuleId="urn:com:att:xacml:rule:id:e1e8c5c0-e2ba-47d5-9289-6c015305ed21" Effect="Deny"> + <Description>DENY - only if target is in black list and guard is active.</Description> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> + <VariableReference VariableId="isGuardActive"/> + <VariableReference VariableId="isInBlackList"/> + </Apply> + </Condition> + </Rule> + <VariableDefinition VariableId="isInBlackList"> + <Apply FunctionId="urn:oasis:names:tc:xacml:3.0:function:any-of"> + <Function FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"/> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="urn:oasis:names:tc:xacml:1.0:target:target-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Apply> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-bag"> + ${blackListElement} + <!-- <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">vserver.vserver-name</AttributeValue>--> + </Apply> + </Apply> + </VariableDefinition> + <VariableDefinition VariableId="isGuardActive"> + <Apply FunctionId="urn:oasis:names:tc:xacml:2.0:function:time-in-range"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only"> + <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time" DataType="http://www.w3.org/2001/XMLSchema#time" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" MustBePresent="false"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveStart}</AttributeValue> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveEnd}</AttributeValue> + </Apply> + </VariableDefinition> +</Policy> diff --git a/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template.xml b/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template.xml new file mode 100644 index 000000000..221fd6ddf --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="urn:com:att:xacml:policy:id:25e12b06-11d5-4895-b2a2-6f6c594de069" Version="1" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny"> + <Description>Policy for frequency limiter.</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${actor}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="urn:oasis:names:tc:xacml:1.0:actor:actor-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${recipe}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" AttributeId="urn:oasis:names:tc:xacml:1.0:operation:operation-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Rule RuleId="urn:com:att:xacml:rule:id:e1e8c5c0-e2ba-47d5-9289-6c015305ed21" Effect="Deny"> + <Description>DENY - only if number of operations performed in the past is larger than the limit and the Guard is active.</Description> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> + <VariableReference VariableId="isGuardActive"/> + <VariableReference VariableId="isHistoryGreaterThanLimit"/> + </Apply> + </Condition> + </Rule> + <VariableDefinition VariableId="isGuardActive"> + <Apply FunctionId="urn:oasis:names:tc:xacml:2.0:function:time-in-range"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only"> + <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time" DataType="http://www.w3.org/2001/XMLSchema#time" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" MustBePresent="false"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveStart}</AttributeValue> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveEnd}</AttributeValue> + </Apply> + </VariableDefinition> + <VariableDefinition VariableId="isHistoryGreaterThanLimit"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:research:xacml:test:sql:resource:operations:count" DataType="http://www.w3.org/2001/XMLSchema#integer" Issuer="com:att:research:xacml:guard:historydb:tw:${twValue}:${twUnits}" MustBePresent="false"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">${limit}</AttributeValue> + </Apply> + </VariableDefinition> +</Policy> diff --git a/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template_old.xml b/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template_old.xml new file mode 100644 index 000000000..45cc5d829 --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/frequency_limiter_template_old.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="urn:com:att:xacml:policy:id:25e12b06-11d5-4895-b2a2-6f6c594de069" Version="1" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-unless-deny"> + <Description>Policy for frequency limiter.</Description> + <Target> + <AnyOf> + <AllOf> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${actor}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="urn:oasis:names:tc:xacml:1.0:actor:actor-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">${recipe}</AttributeValue> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" AttributeId="urn:oasis:names:tc:xacml:1.0:operation:operation-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="false"/> + </Match> + </AllOf> + </AnyOf> + </Target> + <Rule RuleId="urn:com:att:xacml:rule:id:e1e8c5c0-e2ba-47d5-9289-6c015305ed21" Effect="Deny"> + <Description>DENY - only if number of operations performed in the past is larger than the limit and the Guard is active.</Description> + <Condition> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> + <VariableReference VariableId="isGuardActive"/> + <VariableReference VariableId="isHistoryGreaterThanLimit"/> + </Apply> + </Condition> + </Rule> + <VariableDefinition VariableId="isGuardActive"> + <Apply FunctionId="urn:oasis:names:tc:xacml:2.0:function:time-in-range"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only"> + <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:environment:current-time" DataType="http://www.w3.org/2001/XMLSchema#time" Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" MustBePresent="false"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveStart}</AttributeValue> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">${guardActiveEnd}</AttributeValue> + </Apply> + </VariableDefinition> + <VariableDefinition VariableId="isHistoryGreaterThanLimit"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-greater-than-or-equal"> + <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:integer-one-and-only"> + <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="com:att:research:xacml:test:sql:resource:operations:count" DataType="http://www.w3.org/2001/XMLSchema#integer" Issuer="com:att:research:xacml:test:sql:${timeWindow}" MustBePresent="false"/> + </Apply> + <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#integer">${limit}</AttributeValue> + </Apply> + </VariableDefinition> +</Policy> diff --git a/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1610_v1.1_xacml_guard.drl b/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1610_v1.1_xacml_guard.drl new file mode 100644 index 000000000..a743502ce --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1610_v1.1_xacml_guard.drl @@ -0,0 +1,867 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2016 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.ecomp.policy.controlloop; + +import com.att.ecomp.policy.controlloop.ATTControlLoopEvent; +import org.openecomp.policy.controlloop.VirtualControlLoopEvent; +import org.openecomp.policy.controlloop.VirtualControlLoopNotification; +import org.openecomp.policy.controlloop.ControlLoopEventStatus; +import com.att.ecomp.policy.controlloop.ATTControlLoopNotification; +import org.openecomp.policy.controlloop.ControlLoopNotificationType; +import com.att.ecomp.policy.controlloop.ControlLoopLogger; +import com.att.ecomp.policy.controlloop.policy.PolicyResult; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopEventManager; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopOperationManager; +import org.openecomp.policy.appc.Request; +import org.openecomp.policy.appc.Response; +import org.openecomp.policy.appc.CommonHeader; +import com.att.ecomp.policy.guard.PolicyGuard; +import com.att.ecomp.policy.guard.PolicyGuard.LockResult; +import com.att.ecomp.policy.guard.TargetLock; +import com.att.ecomp.policy.guard.GuardResult; +import com.att.ecomp.policy.guard.PolicyGuardRequest; +import com.att.ecomp.policy.guard.PolicyGuardResponse; +import com.att.ecomp.policy.guard.PolicyGuardXacmlRequestAttributes; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.std.annotations.RequestParser; +import com.att.ecomp.policy.guard.PolicyGuardXacmlHelper; + +// +// REPLACE THESE WITH PRODUCTION VERSIONS +// +import com.att.ecomp.policy.controlloop.ControlLoopLogger; +import com.att.ecomp.policy.drools.PolicyEngine; + +global ControlLoopLogger Logger; +global PolicyEngine Engine; +global PDPEngine XacmlPdpEngine; + +import java.time.Instant; +import java.util.LinkedList; +import java.util.Iterator; + +declare Params + closedLoopControlName : String + controlLoopYaml : String +end + +declare OperationTimer + closedLoopControlName : String + requestID : String + delay : String +end + +declare ControlLoopTimer + closedLoopControlName : String + requestID : String + delay : String +end + + +/* +* +* Called once and only once to insert the parameters into working memory for this Closed Loop policy. +* +*/ +rule "${policyName}.SETUP" + when + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Params params = new Params(); + params.setClosedLoopControlName("${closedLoopControlName}"); + params.setControlLoopYaml("${controlLoopYaml}"); + insert(params); + Logger.metrics("Inserted " + params); + Logger.info("------------------------------------------------------------------------------------------------"); +end + +/* +* +* This rule responds to DCAE Events where there is no manager yet. Either it is +* the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled) +* +*/ +rule "${policyName}.EVENT" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + not ( ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) ) + then + try { + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + // + // Check the event, because we need it to not be null when + // we create the ControlLoopEventManager. The ControlLoopEventManager + // will do extra syntax checking as well check if the closed loop is disabled. + // + if ($event.requestID == null) { + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Missing requestID"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } else { + // + // Create an EventManager + // + ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(), $event.requestID); + // + // Determine if EventManager can actively process the event (i.e. syntax, is_closed_loop_disabled checks etc.) + // + VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event); + notification.from = "pdp-0001-controller=controlloop"; // Engine.getInstanceName() + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Are we actively pursuing this event? + // + if (notification.notification == ControlLoopNotificationType.ACTIVE) { + // + // Insert Event Manager into memory, this will now kick off processing. + // + insert(manager); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Setup the Overall Control Loop timer + // + ControlLoopTimer clTimer = new ControlLoopTimer(); + clTimer.setClosedLoopControlName($event.closedLoopControlName); + clTimer.setRequestID($event.requestID.toString()); + clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s"); + // + // Insert it + // + insert(clTimer); + } else { + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } + // + // Now that the manager is inserted into Drools working memory, we'll wait for + // another rule to fire in order to continue processing. This way we can also + // then screen for additional ONSET and ABATED events for this RequestID. + // + } + } catch (Exception e) { + e.printStackTrace(); + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract the event + // + retract($event); + } +end + +/* +* +* This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager +* is now created. We can start processing the yaml specification via the Event Manager. +* +*/ +rule "${policyName}.EVENT.MANAGER" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($clTimer); + // + // Check which event this is. + // + ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event); + Logger.info("Event status is " + eventStatus); + // + // Check what kind of event this is + // + if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) { + // + // We don't care about subsequent onsets + // + Logger.info("Retracting Subsequent Onset " + $event); + retract($event); + return; + } + if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) { + // + // Ignore any bad syntax events + // + Logger.info("Retracting Bad Syntax Event " + $event); + retract($event); + return; + } + // + // We only want the initial ONSET event in memory, + // all the other events need to be retracted to support + // cleanup and avoid the other rules being fired for this event. + // + if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) { + Logger.info("Retracting Event " + $event); + retract($event); + } + Logger.info("Checking due to new event " + $event.triggerID); + // + // Now start seeing if we need to process this event + // + try { + // + // Check if this is a Final Event + // + ATTControlLoopNotification notification = $manager.isControlLoopFinal(); + + + if (notification != null) { + // + // Its final, but are we waiting for abatement? + // + if ($manager.getNumAbatements() > 0) { + Logger.info("Abatement received, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + // + // TODO - what if we get subsequent Events for this RequestID? + // By default, it will all start over again. May be confusing for Ruby. + // Or, we could track this and then subsequently ignore the events + // + } else { + // + // Check whether we need to wait for abatement + // + if ($manager.getProcessor().getControlLoop().abatement == true && notification.notification == ControlLoopNotificationType.FINAL_SUCCESS) { + Logger.info("Waiting for abatement."); + } else { + Logger.info("No abatement is promised to come, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + } + } + } else { + // + // NOT final, so let's ask for the next operation + // + ControlLoopOperationManager operation = $manager.processControlLoop(); + if (operation != null) { + Logger.info("starting a new operation" + operation); + // + // insert into memory + // + insert(operation); + // + // insert operation timeout object + // + OperationTimer opTimer = new OperationTimer(); + opTimer.setClosedLoopControlName($event.closedLoopControlName); + opTimer.setRequestID($event.requestID.toString()); + opTimer.setDelay(operation.getOperationTimeout().toString() + "s"); + insert(opTimer); + + // + // Let's ask for a lock right away + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("manager returned lock " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } + } else { + // + // Probably waiting for abatement + // + } + } + } catch (Exception e) { + e.printStackTrace(); + /* + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // TODO should we abort if we get an exception? + // + */ + } + +end + +/* +* +* +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.NOT_LOCKED.TIMEOUT" + timer (int: 5s 5s) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + not ( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + // + // Need to ask for a Lock + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("Lock acquired: " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } +end + +/* +* +* +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "Permit" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + // + // Start the Operation + // + //Object request = $operation.startOperation($event); + //$operation.startOperation($event); + Object request = $operation.getOperationRequest(); + + if (request != null) { + Logger.info("Starting operation"); + // + // Tell interested parties we are performing this Operation + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage(); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Send the APPC request + // + if (request instanceof Request) { + Engine.deliver("UEB", "APPC-CL", request); + } + // + // TODO: send different types of requests + // + + } else { + // + // What happens if its null? + // + } +end + + +/* +* +* +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "NONE" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + + $operation.startOperation($event); + // + // Now send Guard Request to XACML Guard + // + PolicyGuardXacmlRequestAttributes xacmlReq = new PolicyGuardXacmlRequestAttributes($operation.policy.actor.toString(), $operation.policy.recipe, $event.target, $event.requestID.toString()); + //Engine.deliver("UEB", "GUARD-CL", xacmlReq/*request*/); + System.out.println("\n********** XACML REQUEST START ********"); + System.out.println(RequestParser.parseRequest(xacmlReq)); + System.out.println("********** XACML REQUEST END ********\n"); + + com.att.research.xacml.api.Response xacmlResponse = PolicyGuardXacmlHelper.callPDP(XacmlPdpEngine, "", (com.att.research.xacml.api.Request) RequestParser.parseRequest(xacmlReq), false); + + System.out.println("\n********** XACML RESPONSE 1 START ********"); + System.out.println(xacmlResponse); + System.out.println("********** XACML RESPONSE 1 END ********\n"); + + PolicyGuardResponse guardResponse = PolicyGuardXacmlHelper.ParseXacmlPdpResponse(xacmlResponse); + System.out.println("\n\n============ Guard inserted with decision "+ guardResponse.result + " !!! ===========\n\n"); + + + insert(guardResponse); + +end + + + +rule "${policyName}.GUARD.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $lock : TargetLock (requestID == $event.requestID) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $guardResponse : PolicyGuardResponse(/*requestID == $event.requestID, $operation.policy.recipe == operation*/) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($operation); + Logger.metrics($lock); + Logger.metrics($guardResponse); + + + //we will permit the operation if there was no Guard for it + if($guardResponse.result == "Indeterminate"){ + $guardResponse.result = "Permit"; + } + + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage($guardResponse.result);//"Guard result: " + $guardResponse.result; + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + + + if($guardResponse.result == "Permit"){ + + modify($operation){setGuardApprovalStatus($guardResponse.result)}; + } + else { + //This is the Deny case + $operation.setOperationHasGuardDeny(); + retract($opTimer); + retract($operation); + modify($manager) {finishOperation($operation)}; + } + + retract($guardResponse); + +end + + + + +/* +* +* This rule responds to APPC Response Events +* +* I would have like to be consistent and write the Response like this: +* $response : Response( CommonHeader.RequestID == $onset.requestID ) +* +* However, no compile error was given. But a runtime error was given. I think +* because drools is confused between the classname CommonHeader vs the property CommonHeader. +* +*/ +rule "${policyName}.APPC.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $lock : TargetLock (requestID == $event.requestID) + $response : Response( getCommonHeader().RequestID == $event.requestID ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + Logger.metrics($response); + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + Logger.info("operation finished with result: " + policyResult); + // + // This Operation has completed, construct a notification showing our results + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } else { + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // We must also retract the timer object + // NOTE: We could write a Rule to do this + // + retract($opTimer); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } + } else { + // + // Its not finished yet (i.e. expecting more Response objects) + // + // Or possibly it is a leftover response that we timed the request out previously + // + } + // + // We are going to retract these objects from memory + // + retract($response); +end + +/* +* +* The problem with Responses is that they don't have a controlLoopControlName +* field in them, so the only way to attach them is via RequestID. If we have multiple +* control loop .drl's loaded in the same container, we need to be sure the cleanup +* rules don't remove Responses for other control loops. +* +*/ +rule "${policyName}.APPC.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : Response($id : getCommonHeader().RequestID ) + not ( ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + // + // Retract it + // + retract($response); +end +/* +* +* This is the timer that manages the timeout for an individual operation. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + // + // Tell it its timed out + // + $operation.setOperationHasTimedOut(); + // + // Create a notification for it + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Get rid of the timer + // + retract($opTimer); + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } +end + +/* +* +* This is the timer that manages the overall control loop timeout. +* +*/ +rule "${policyName}.EVENT.MANAGER.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $operations : LinkedList() + from collect( ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) ) + $opTimers : LinkedList() + from collect( OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) ) + $locks : LinkedList() + from collect( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($clTimer); + if ($operations == null) { + Logger.info("no operations found"); + } else { + Logger.info("found " + $operations.size() + " operations"); + } + // + // Tell the Event Manager it has timed out + // + VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut(); + if (notification != null) { + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Retract EVERYTHING + // + retract($event); + retract($manager); + retract($clTimer); + if ($operations != null && $operations.size() > 0) { + Iterator<ControlLoopOperationManager> iter = $operations.iterator(); + while (iter.hasNext()) { + ControlLoopOperationManager manager = iter.next(); + retract(manager); + } + } + if ($opTimers != null && $opTimers.size() > 0) { + Iterator<OperationTimer> iter = $opTimers.iterator(); + while (iter.hasNext()) { + OperationTimer opTimer = iter.next(); + retract(opTimer); + } + } + if ($locks != null && $locks.size() > 0) { + Iterator<TargetLock> iter = $locks.iterator(); + while (iter.hasNext()) { + TargetLock lock = iter.next(); + // + // Ensure we release the lock + // + PolicyGuard.unlockTarget(lock); + // + // + // + retract(lock); + } + } +end diff --git a/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1707_xacml_guard_enodeb.drl b/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1707_xacml_guard_enodeb.drl new file mode 100644 index 000000000..b4f160951 --- /dev/null +++ b/controlloop/templates/template.demo/src/main/resources/old/ControlLoop_Template_1707_xacml_guard_enodeb.drl @@ -0,0 +1,952 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2016 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.ecomp.policy.controlloop; + +import com.att.ecomp.policy.controlloop.ATTControlLoopEvent; +import org.openecomp.policy.controlloop.VirtualControlLoopEvent; +import org.openecomp.policy.controlloop.VirtualControlLoopNotification; +import org.openecomp.policy.controlloop.ControlLoopEventStatus; +import com.att.ecomp.policy.controlloop.ATTControlLoopNotification; +import org.openecomp.policy.controlloop.ControlLoopNotificationType; +import com.att.ecomp.policy.controlloop.ControlLoopLogger; +import com.att.ecomp.policy.controlloop.policy.PolicyResult; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopEventManager; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS; +import com.att.ecomp.policy.controlloop.eventmanager.ControlLoopOperationManager; +import org.openecomp.policy.appc.Request; +import org.openecomp.policy.appc.Response; +import org.openecomp.policy.appc.CommonHeader; +import com.att.ecomp.policy.guard.PolicyGuard; +import com.att.ecomp.policy.guard.PolicyGuard.LockResult; +import com.att.ecomp.policy.guard.TargetLock; +import com.att.ecomp.policy.guard.GuardResult; +import com.att.ecomp.policy.guard.PolicyGuardRequest; +import com.att.ecomp.policy.guard.PolicyGuardResponse; +import com.att.ecomp.policy.guard.PolicyGuardXacmlRequestAttributes; +import com.att.research.xacml.api.pdp.PDPEngine; +import com.att.research.xacml.std.annotations.RequestParser; +import com.att.ecomp.policy.guard.PolicyGuardXacmlHelper; +import com.att.ecomp.policy.controlloop.policy.ControlLoopPolicy; +import com.att.ecomp.policy.controlloop.policy.Policy; +import java.net.URLDecoder; +import org.eclipse.persistence.exceptions.DatabaseException; + +// +// REPLACE THESE WITH PRODUCTION VERSIONS +// +import com.att.ecomp.policy.controlloop.ControlLoopLogger; +import com.att.ecomp.policy.drools.PolicyEngine; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.Constructor; + +global ControlLoopLogger Logger; +global PolicyEngine Engine; +global PDPEngine XacmlPdpEngine; + +import java.time.Instant; +import java.util.LinkedList; +import java.util.Iterator; + +declare Params + closedLoopControlName : String + controlLoopYaml : String +end + +declare EnbParams + enbOperationsPeriodicTimer : String +end + + +declare OperationTimer + closedLoopControlName : String + requestID : String + delay : String +end + +declare ControlLoopTimer + closedLoopControlName : String + requestID : String + delay : String +end + + +/* +* +* Called once and only once to insert the parameters into working memory for this Closed Loop policy. +* +*/ +rule "${policyName}.SETUP" + when + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Params params = new Params(); + params.setClosedLoopControlName("${closedLoopControlName}"); + params.setControlLoopYaml("${controlLoopYaml}"); + insert(params); + Logger.metrics("Inserted " + params); + Logger.info("------------------------------------------------------------------------------------------------"); + EnbParams enbParams = new EnbParams(); + + // + //Fetching the eNodeB timer from the Yaml + // + Yaml yaml = new Yaml(new Constructor(ControlLoopPolicy.class)); + Object obj = yaml.load(URLDecoder.decode(params.getControlLoopYaml(), "UTF-8")); + + enbParams.setEnbOperationsPeriodicTimer("0s"); + for(Policy policy : ((ControlLoopPolicy)obj).policies){ + if(policy.actor.equals("APPC")){ + if(policy.payload != null){ + if(policy.payload.containsKey("enbOperationPeriodicTimer")){ + enbParams.setEnbOperationsPeriodicTimer(policy.payload.get("enbOperationPeriodicTimer")); + } + } + break; + } + } + insert(enbParams); + System.out.println("################ got timer: " + enbParams.getEnbOperationsPeriodicTimer()); + +end + +/* +* +* This rule responds to DCAE Events where there is no manager yet. Either it is +* the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled) +* +*/ +rule "${policyName}.EVENT" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + not ( ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) ) + then + try { + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + // + // Check the event, because we need it to not be null when + // we create the ControlLoopEventManager. The ControlLoopEventManager + // will do extra syntax checking as well check if the closed loop is disabled. + // + if ($event.requestID == null) { + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Missing requestID"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } else { + // + // Create an EventManager + // + ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(), $event.requestID); + // + // Determine if EventManager can actively process the event (i.e. syntax, is_closed_loop_disabled checks etc.) + // + VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event); + notification.from = "pdp-0001-controller=controlloop"; // Engine.getInstanceName() + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Are we actively pursuing this event? + // + if (notification.notification == ControlLoopNotificationType.ACTIVE) { + // + // Insert Event Manager into memory, this will now kick off processing. + // + insert(manager); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Setup the Overall Control Loop timer + // + ControlLoopTimer clTimer = new ControlLoopTimer(); + clTimer.setClosedLoopControlName($event.closedLoopControlName); + clTimer.setRequestID($event.requestID.toString()); + clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s"); + // + // Insert it + // + insert(clTimer); + } else { + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract it from memory + // + retract($event); + } + // + // Now that the manager is inserted into Drools working memory, we'll wait for + // another rule to fire in order to continue processing. This way we can also + // then screen for additional ONSET and ABATED events for this RequestID. + // + } + } catch (Exception e) { + e.printStackTrace(); + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Retract the event + // + retract($event); + } +end + +/* +* +* This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager +* is now created. We can start processing the yaml specification via the Event Manager. +* +*/ +rule "${policyName}.EVENT.MANAGER" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($clTimer); + // + // Check which event this is. + // + ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event); + Logger.info("Event status is " + eventStatus); + // + // Check what kind of event this is + // + if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) { + // + // We don't care about subsequent onsets + // + Logger.info("Retracting Subsequent Onset " + $event); + retract($event); + return; + } + if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) { + // + // Ignore any bad syntax events + // + Logger.info("Retracting Bad Syntax Event " + $event); + retract($event); + return; + } + // + // We only want the initial ONSET event in memory, + // all the other events need to be retracted to support + // cleanup and avoid the other rules being fired for this event. + // + if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) { + Logger.info("Retracting Event " + $event); + retract($event); + } + Logger.info("Checking due to new event " + $event.triggerID); + // + // Now start seeing if we need to process this event + // + try { + // + // Check if this is a Final Event + // + ATTControlLoopNotification notification = $manager.isControlLoopFinal(); + + + if (notification != null) { + // + // Its final, but are we waiting for abatement? + // + if ($manager.getNumAbatements() > 0) { + Logger.info("Abatement received, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + // + // TODO - what if we get subsequent Events for this RequestID? + // By default, it will all start over again. May be confusing for Ruby. + // Or, we could track this and then subsequently ignore the events + // + } else { + // + // Check whether we need to wait for abatement + // + if ($manager.getProcessor().getControlLoop().abatement == true && notification.notification == ControlLoopNotificationType.FINAL_SUCCESS) { + Logger.info("Waiting for abatement."); + } else { + Logger.info("No abatement is promised to come, close out the control loop for " + $event.requestID); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // In this case, we are done + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Unlock the target + // + TargetLock lock = $manager.unlockCurrentOperation(); + if (lock != null) { + System.out.println("retracting lock " + lock); + retract(lock); + } + // + // Retract everything from memory + // + System.out.println("retracting onset"); + retract($manager.getOnsetEvent()); + retract($manager); + retract($clTimer); + } + } + } else { + // + // NOT final, so let's ask for the next operation + // + ControlLoopOperationManager operation = $manager.processControlLoop(); + if (operation != null) { + Logger.info("starting a new operation" + operation); + // + // insert into memory + // + insert(operation); + // + // insert operation timeout object + // + OperationTimer opTimer = new OperationTimer(); + opTimer.setClosedLoopControlName($event.closedLoopControlName); + opTimer.setRequestID($event.requestID.toString()); + opTimer.setDelay(operation.getOperationTimeout().toString() + "s"); + insert(opTimer); + + // + // Let's ask for a lock right away + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("manager returned lock " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } + } else { + // + // Probably waiting for abatement + // + } + } + } catch (Exception e) { + e.printStackTrace(); + /* + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.REJECTED; + notification.from = "policy"; + notification.message = "Exception occurred " + e.getMessage(); + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // TODO should we abort if we get an exception? + // + */ + } + +end + +/* +* +* +* +*/ +rule "${policyName}.PERIODIC_CHECK_OF_PENDING_ENB_OPERATIONS" + timer (expr: "0s", $t) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $enbParams : EnbParams($t : getEnbOperationsPeriodicTimer()) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $operations : LinkedList(size() > 0) + from collect( ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName) ) + + then + System.out.println(drools.getRule().getName() + " ********** operations size: " + $operations.size()); + //System.out.println(drools.getRule().getName()); + //The limt of 5 should also be defined in Yaml. +end + + +/* +* +* +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.NOT_LOCKED.TIMEOUT" + timer (int: 5s 5s) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + not ( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + // + // Need to ask for a Lock + // + LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation(); + if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) { + Logger.info("Lock acquired: " + result.getB()); + // + // Insert into memory + // + insert(result.getB()); + } +end + +/* +* +* Guard Permitted, let's send request to the actor. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "Permit" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + + + Object request = $operation.getOperationRequest(); + + if (request != null) { + Logger.info("Starting operation"); + // + // Tell interested parties we are performing this Operation + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage(); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + switch ($operation.policy.actor){ + + case "APPC": + + if (request instanceof Request) { + Engine.deliver("UEB", "APPC-CL", request); + } + case "SDNR": + default: + } + + + } else { + // + // What happens if its null? + // + } +end + + +/* +* +* We were able to acquire a lock so now let's ask Xacml Guard whether we are allowed to proceed with the request to the actor. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "NONE" ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($lock); + + + + + // + // We are starting the operation but the actor won't be contacted until Guard is queried and permitted. + // + $operation.startOperation($event); + + // + // Sending notification that we are about to query Guard ("DB write - start operation") + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage(); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + // + // Now send Guard Request to XACML Guard. In order to bypass the call to Guard, just change guardEnabled to false. + // + // In order to use REST XACML, provide a URL instead of "" as a second argument o the CallGuardTask() and set the first + // argument to null (instead of XacmlPdpEngine). + // + boolean guardEnabled = true; + + if(guardEnabled){ + + Thread t = new Thread(new com.att.ecomp.policy.guard.CallGuardTask( + XacmlPdpEngine, + "", + drools.getWorkingMemory(), + $operation.policy.actor.toString(), + $operation.policy.recipe, + $event.target, + $event.requestID.toString() + )); + t.start(); + } + else{ + insert(new PolicyGuardResponse("Permit", $event.requestID, $operation.policy.recipe)); + } + + + + +end + +// +//This rule will be triggered when a thread talking to the XACML Guard inserts a guardResponse object into the working memory +// +rule "${policyName}.GUARD.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $lock : TargetLock (requestID == $event.requestID) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $guardResponse : PolicyGuardResponse(requestID == $event.requestID, $operation.policy.recipe == operation) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($operation); + Logger.metrics($lock); + Logger.metrics($guardResponse); + + + //we will permit the operation if there was no Guard for it + if($guardResponse.result == "Indeterminate"){ + $guardResponse.result = "Permit"; + } + + // + // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny") + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.notification = ControlLoopNotificationType.OPERATION; + notification.message = $operation.getOperationMessage($guardResponse.result); + notification.history = $operation.getHistory(); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + + + + if($guardResponse.result == "Permit"){ + + modify($operation){setGuardApprovalStatus($guardResponse.result)}; + } + else { + //This is the Deny case + $operation.setOperationHasGuardDeny(); + retract($opTimer); + retract($operation); + modify($manager) {finishOperation($operation)}; + } + + retract($guardResponse); + +end + + + + +/* +* +* This rule responds to APPC Response Events +* +* I would have like to be consistent and write the Response like this: +* $response : Response( CommonHeader.RequestID == $onset.requestID ) +* +* However, no compile error was given. But a runtime error was given. I think +* because drools is confused between the classname CommonHeader vs the property CommonHeader. +* +*/ +rule "${policyName}.APPC.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $lock : TargetLock (requestID == $event.requestID) + $response : Response( getCommonHeader().RequestID == $event.requestID ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + Logger.metrics($response); + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + Logger.info("operation finished with result: " + policyResult); + // + // This Operation has completed, construct a notification showing our results. (DB write - end operation) + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } else { + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // We must also retract the timer object + // NOTE: We could write a Rule to do this + // + retract($opTimer); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } + } else { + // + // Its not finished yet (i.e. expecting more Response objects) + // + // Or possibly it is a leftover response that we timed the request out previously + // + } + // + // We are going to retract these objects from memory + // + retract($response); +end + +/* +* +* The problem with Responses is that they don't have a controlLoopControlName +* field in them, so the only way to attach them is via RequestID. If we have multiple +* control loop .drl's loaded in the same container, we need to be sure the cleanup +* rules don't remove Responses for other control loops. +* +*/ +rule "${policyName}.APPC.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : Response($id : getCommonHeader().RequestID ) + not ( ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + // + // Retract it + // + retract($response); +end +/* +* +* This is the timer that manages the timeout for an individual operation. +* +*/ +rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $lock : TargetLock (requestID == $event.requestID) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + // + // Tell it its timed out + // + $operation.setOperationHasTimedOut(); + // + // Create a notification for it ("DB Write - end operation") + // + ATTControlLoopNotification notification = new ATTControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + // + // Get rid of the timer + // + retract($opTimer); + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } +end + +/* +* +* This is the timer that manages the overall control loop timeout. +* +*/ +rule "${policyName}.EVENT.MANAGER.TIMEOUT" + timer (expr: $to ) + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : ATTControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() ) + $operations : LinkedList() + from collect( ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) ) + $opTimers : LinkedList() + from collect( OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) ) + $locks : LinkedList() + from collect( TargetLock (requestID == $event.requestID) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($manager); + Logger.metrics($clTimer); + if ($operations == null) { + Logger.info("no operations found"); + } else { + Logger.info("found " + $operations.size() + " operations"); + } + // + // Tell the Event Manager it has timed out + // + VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut(); + if (notification != null) { + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Retract EVERYTHING + // + retract($event); + retract($manager); + retract($clTimer); + if ($operations != null && $operations.size() > 0) { + Iterator<ControlLoopOperationManager> iter = $operations.iterator(); + while (iter.hasNext()) { + ControlLoopOperationManager manager = iter.next(); + retract(manager); + } + } + if ($opTimers != null && $opTimers.size() > 0) { + Iterator<OperationTimer> iter = $opTimers.iterator(); + while (iter.hasNext()) { + OperationTimer opTimer = iter.next(); + retract(opTimer); + } + } + if ($locks != null && $locks.size() > 0) { + Iterator<TargetLock> iter = $locks.iterator(); + while (iter.hasNext()) { + TargetLock lock = iter.next(); + // + // Ensure we release the lock + // + PolicyGuard.unlockTarget(lock); + // + // + // + retract(lock); + } + } +end |