/* * 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 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 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 iter = $operations.iterator(); while (iter.hasNext()) { ControlLoopOperationManager manager = iter.next(); retract(manager); } } if ($opTimers != null && $opTimers.size() > 0) { Iterator iter = $opTimers.iterator(); while (iter.hasNext()) { OperationTimer opTimer = iter.next(); retract(opTimer); } } if ($locks != null && $locks.size() > 0) { Iterator iter = $locks.iterator(); while (iter.hasNext()) { TargetLock lock = iter.next(); // // Ensure we release the lock // PolicyGuard.unlockTarget(lock); // // // retract(lock); } } end