fc0cd29b7c2a792b6bd905e2cf0ee69e170de2aa
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.controlloop;
22
23 import org.onap.policy.controlloop.VirtualControlLoopEvent;
24 import org.onap.policy.controlloop.VirtualControlLoopNotification;
25 import org.onap.policy.controlloop.ControlLoopEventStatus;
26 import org.onap.policy.controlloop.ControlLoopNotificationType;
27 import org.onap.policy.controlloop.ControlLoopLogger;
28 import org.onap.policy.controlloop.policy.PolicyResult;
29 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
30 import org.onap.policy.controlloop.policy.Policy;
31 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
32 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NEW_EVENT_STATUS;
33 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
34 import org.onap.policy.controlloop.actor.so.SOActorServiceProvider;
35 import org.onap.policy.appc.Request;
36 import org.onap.policy.appc.Response;
37 import org.onap.policy.appc.CommonHeader;
38 import org.onap.policy.appclcm.LCMRequestWrapper;
39 import org.onap.policy.appclcm.LCMResponseWrapper;
40 import org.onap.policy.appclcm.LCMRequest;
41 import org.onap.policy.appclcm.LCMResponse;
42 import org.onap.policy.appclcm.LCMCommonHeader;
43 import org.onap.policy.vfc.VFCRequest;
44 import org.onap.policy.vfc.VFCResponse;
45 import org.onap.policy.vfc.VFCManager;
46 import org.onap.policy.so.SOManager;
47 import org.onap.policy.so.SORequest;
48 import org.onap.policy.so.SORequestStatus;
49 import org.onap.policy.so.SORequestDetails;
50 import org.onap.policy.so.SOModelInfo;
51 import org.onap.policy.so.SOCloudConfiguration;
52 import org.onap.policy.so.SORequestInfo;
53 import org.onap.policy.so.SORequestParameters;
54 import org.onap.policy.so.SORelatedInstanceListElement;
55 import org.onap.policy.so.SORelatedInstance;
56 import org.onap.policy.so.SOResponse;
57 import org.onap.policy.guard.PolicyGuard;
58 import org.onap.policy.guard.PolicyGuard.LockResult;
59 import org.onap.policy.guard.TargetLock;
60 import org.onap.policy.guard.GuardResult;
61 import org.onap.policy.guard.PolicyGuardRequest;
62 import org.onap.policy.guard.PolicyGuardResponse;
63 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
64 import org.onap.policy.guard.PolicyGuardXacmlHelper;
65
66 import org.yaml.snakeyaml.Yaml;
67 import org.yaml.snakeyaml.constructor.Constructor;
68
69 import org.slf4j.LoggerFactory;
70 import org.slf4j.Logger;
71
72 import java.time.Instant;
73 import java.util.LinkedList;
74 import java.util.Iterator;
75
76 import org.onap.policy.drools.system.PolicyEngine;
77
78 declare Params
79   closedLoopControlName : String
80   controlLoopYaml : String
81 end
82
83
84 declare OperationTimer
85   closedLoopControlName : String
86   requestID : String
87   delay : String
88 end
89
90 declare ControlLoopTimer
91   closedLoopControlName : String
92   requestID : String
93   delay : String
94 end
95
96 /*
97 *
98 * Called once and only once to insert the parameters into working memory for this Closed Loop policy.
99 *
100 */
101 rule "${policyName}.SETUP"
102     when
103     then
104     
105     Params params = new Params();
106     params.setClosedLoopControlName("${closedLoopControlName}");
107     params.setControlLoopYaml("${controlLoopYaml}");
108     insert(params);
109
110     // Note: globals have bad behavior when persistence is used,
111     //       hence explicitly getting the logger vs using a global
112     
113     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
114     logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(), params.getControlLoopYaml());
115     
116     String sqlDbUsername = PolicyEngine.manager.getEnvironmentProperty("sql.db.username");
117     
118     String aaiUrl = PolicyEngine.manager.getEnvironmentProperty("aai.url");
119     String aaiUsername = PolicyEngine.manager.getEnvironmentProperty("aai.username");
120     String aaiPassword = PolicyEngine.manager.getEnvironmentProperty("aai.password");
121     
122     String soUrl =PolicyEngine.manager.getEnvironmentProperty("so.url");
123     String soUsername = PolicyEngine.manager.getEnvironmentProperty("so.username");
124     String soPassword = PolicyEngine.manager.getEnvironmentProperty("so.password");
125     
126     String vfcUrl =PolicyEngine.manager.getEnvironmentProperty("vfc.url");
127     String vfcUsername = PolicyEngine.manager.getEnvironmentProperty("vfc.username");
128     String vfcPassword = PolicyEngine.manager.getEnvironmentProperty("vfc.password");
129     
130     String guardUrl = PolicyEngine.manager.getEnvironmentProperty("guard.url");
131     String guardUsername = PolicyEngine.manager.getEnvironmentProperty("pdpx.username");
132     String guardPassword = PolicyEngine.manager.getEnvironmentProperty("pdpx.password");
133     String guardJdbcUrl = PolicyEngine.manager.getEnvironmentProperty("guard.jdbc.url");
134     String guardDisabled = PolicyEngine.manager.getEnvironmentProperty("guard.disabled");
135     
136     logger.info("{}: {} : AAI=[{}:{}]", params.getClosedLoopControlName(), drools.getRule().getName(), aaiUrl, aaiUsername);
137     logger.info("{}: {} : SO=[{}:{}]", params.getClosedLoopControlName(), drools.getRule().getName(), soUrl, soUsername);
138     logger.info("{}: {} : VFC=[{}:{}]", params.getClosedLoopControlName(), drools.getRule().getName(), vfcUrl, vfcUsername);
139     logger.info("{}: {} : GUARD=[{}:{}:{}:{}]", params.getClosedLoopControlName(), drools.getRule().getName(), guardUrl, guardUsername, guardJdbcUrl, guardDisabled);
140     logger.info("{}: {} : DB=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(), sqlDbUsername);
141 end
142
143 /*
144 *
145 * This rule responds to DCAE Events where there is no manager yet. Either it is
146 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
147 *
148 */
149 rule "${policyName}.EVENT"
150     when
151         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
152         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
153         not ( ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) )
154     then
155  
156     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
157     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
158     
159     try {
160       
161         //
162         // Check the event, because we need it to not be null when
163         // we create the ControlLoopEventManager. The ControlLoopEventManager
164         // will do extra syntax checking as well check if the closed loop is disabled.
165         //
166         if ($event.requestID == null) {
167             VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
168             notification.notification = ControlLoopNotificationType.REJECTED;
169             notification.from = "policy";
170             notification.message = "Missing requestID";
171             notification.policyName = drools.getRule().getName();
172             notification.policyScope = "${policyScope}";
173             notification.policyVersion = "${policyVersion}";
174             
175             //
176             // Let interested parties know
177             //
178             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
179             
180             //
181             // Retract it from memory
182             //
183             retract($event);
184         } else {
185             //
186             // Create an EventManager
187             //
188             ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(), $event.requestID);
189             //
190             // Determine if EventManager can actively process the event (i.e. syntax, is_closed_loop_disabled checks etc.)
191             //
192             VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
193             notification.from = "pdp-0001-controller=controlloop"; // Engine.getInstanceName()
194             notification.policyName = drools.getRule().getName();
195             notification.policyScope = "${policyScope}";
196             notification.policyVersion = "${policyVersion}";
197             //
198             // Are we actively pursuing this event?
199             //
200             if (notification.notification == ControlLoopNotificationType.ACTIVE) {
201                 //
202                 // Insert Event Manager into memory, this will now kick off processing.
203                 //
204                 insert(manager);
205                 //
206                 // Let interested parties know
207                 //
208                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
209                 //
210                 // Setup the Overall Control Loop timer
211                 //
212                 ControlLoopTimer clTimer = new ControlLoopTimer();
213                 clTimer.setClosedLoopControlName($event.closedLoopControlName);
214                 clTimer.setRequestID($event.requestID.toString());
215                 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
216                 //
217                 // Insert it
218                 //
219                 insert(clTimer);
220             } else {
221                 //
222                 // Let interested parties know
223                 //
224                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
225                 //
226                 // Retract it from memory
227                 //
228                 retract($event);
229             }
230             
231             //
232             // Now that the manager is inserted into Drools working memory, we'll wait for
233             // another rule to fire in order to continue processing. This way we can also
234             // then screen for additional ONSET and ABATED events for this RequestID.
235             //
236         }
237     } catch (Exception e) {
238         logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
239         
240         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
241         notification.notification = ControlLoopNotificationType.REJECTED;
242         notification.message = "Exception occurred " + e.getMessage();
243         notification.policyName = drools.getRule().getName();
244         notification.policyScope = "${policyScope}";
245         notification.policyVersion = "${policyVersion}";
246         //
247         //
248         //
249         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
250         //
251         // Retract the event
252         //
253         retract($event);
254     }
255 end
256
257 /*
258 *
259 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
260 * is now created. We can start processing the yaml specification via the Event Manager.
261 *
262 */
263 rule "${policyName}.EVENT.MANAGER"
264     when
265         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
266         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
267         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
268         $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
269     then
270
271     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
272     logger.info("{}: {}: event={} manager={} clTimer={}", 
273                 $params.getClosedLoopControlName(), drools.getRule().getName(),
274                 $event, $manager, $clTimer);
275     //
276     // Check which event this is.
277     //
278     ControlLoopEventManager.NEW_EVENT_STATUS eventStatus = $manager.onNewEvent($event);
279
280     //
281     // Check what kind of event this is
282     //
283     if (eventStatus == NEW_EVENT_STATUS.SUBSEQUENT_ONSET) {
284         //
285         // We don't care about subsequent onsets
286         //
287         logger.info("{}: {}: subsequent onset", 
288                     $params.getClosedLoopControlName(), drools.getRule().getName());
289         retract($event);
290         return;
291     }
292     if (eventStatus == NEW_EVENT_STATUS.SYNTAX_ERROR) {
293         //
294         // Ignore any bad syntax events
295         //
296         logger.warn("{}: {}: syntax error", 
297                     $params.getClosedLoopControlName(), drools.getRule().getName());
298         retract($event);
299         return;
300     }
301     //
302     // We only want the initial ONSET event in memory,
303     // all the other events need to be retracted to support
304     // cleanup and avoid the other rules being fired for this event.
305     //
306     if (eventStatus != NEW_EVENT_STATUS.FIRST_ONSET) {
307         logger.warn("{}: {}: no first onset", 
308                     $params.getClosedLoopControlName(), drools.getRule().getName());
309         retract($event);
310     }
311     
312     logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(), 
313                  drools.getRule().getName(), $event.target);
314     //
315     // Now start seeing if we need to process this event
316     //
317     try {
318         //
319         // Check if this is a Final Event
320         //
321         VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
322     
323     
324         if (notification != null) {
325             //
326             // Its final, but are we waiting for abatement?
327             //
328             if ($manager.getNumAbatements() > 0) {
329                 logger.info("{}: {}: abatement received for {}.  Closing the control loop", 
330                             $params.getClosedLoopControlName(), drools.getRule().getName(), 
331                             $event.requestID);
332                 notification.from = "policy";
333                 notification.policyName = drools.getRule().getName();
334                 notification.policyScope = "${policyScope}";
335                 notification.policyVersion = "${policyVersion}";
336                 //
337                 // In this case, we are done
338                 //
339                 PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
340                 //
341                 // Unlock the target
342                 //
343                 TargetLock lock = $manager.unlockCurrentOperation();
344                 if (lock != null) {
345                     logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(), 
346                                  drools.getRule().getName(), lock);
347                     retract(lock);
348                 }
349                 //
350                 // Retract everything from memory
351                 //
352                 logger.info("{}: {}: retracting onset, manager, and timer", 
353                             $params.getClosedLoopControlName(), drools.getRule().getName());
354                 
355                 retract($manager.getOnsetEvent());
356                 retract($manager);
357                 retract($clTimer);
358                 //
359                 // TODO - what if we get subsequent Events for this RequestID?
360                 // By default, it will all start over again. May be confusing for Ruby.
361                 // Or, we could track this and then subsequently ignore the events
362                 //
363             } else {
364                 //
365                 // Check whether we need to wait for abatement
366                 //
367                 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.notification == ControlLoopNotificationType.FINAL_SUCCESS) {
368                   logger.info("{}: {}: waiting for abatement ..", 
369                               $params.getClosedLoopControlName(), drools.getRule().getName());
370                 } else {
371                   logger.info("{}: {}: no abatement expect for {}.  Closing the control loop", 
372                               $params.getClosedLoopControlName(), drools.getRule().getName(), 
373                               $event.requestID);
374                   
375                   notification.from = "policy";
376                   notification.policyName = drools.getRule().getName();
377                   notification.policyScope = "${policyScope}";
378                   notification.policyVersion = "${policyVersion}";
379                   
380                   //
381                   // In this case, we are done
382                   //
383                   PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
384                   //
385                   // Unlock the target
386                   //
387                   TargetLock lock = $manager.unlockCurrentOperation();
388                   if (lock != null) {
389                       logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(), 
390                                   drools.getRule().getName(), lock);
391                       retract(lock);
392                   }
393                   //
394                   // Retract everything from memory
395                   //
396                   logger.info("{}: {}: retracting onset, manager, and timer", 
397                               $params.getClosedLoopControlName(), drools.getRule().getName());
398                   
399                   retract($manager.getOnsetEvent());
400                   retract($manager);
401                   retract($clTimer);
402                 }
403             }
404         } else {
405             //
406             // NOT final, so let's ask for the next operation
407             //
408             ControlLoopOperationManager operation = $manager.processControlLoop();
409             if (operation != null) {
410               logger.info("{}: {}: starting operation={}", 
411                           $params.getClosedLoopControlName(), drools.getRule().getName(), 
412                           operation);
413               //
414               // insert into memory
415               //
416               insert(operation);
417               //
418               // insert operation timeout object
419               //
420               OperationTimer opTimer = new OperationTimer();
421               opTimer.setClosedLoopControlName($event.closedLoopControlName);
422               opTimer.setRequestID($event.requestID.toString());
423               opTimer.setDelay(operation.getOperationTimeout().toString() + "s");
424               insert(opTimer);
425       
426               //
427               // Let's ask for a lock right away
428               //
429               LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
430               if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
431                 logger.info("{}: {}: guard lock acquired={}", 
432                             $params.getClosedLoopControlName(), drools.getRule().getName(), 
433                             result.getB());
434                 
435                 //
436                 // Insert into memory
437                 //
438                 insert(result.getB());
439               }
440             } else {
441                 //
442                 // Probably waiting for abatement
443                 //
444               logger.info("{}: {}: no operation, probably waiting for abatement", 
445                           $params.getClosedLoopControlName(), drools.getRule().getName());
446             }
447         }
448     } catch (Exception e) {
449       logger.warn("{}: {}: unexpected", 
450                   $params.getClosedLoopControlName(), 
451                   drools.getRule().getName(), e);
452
453       //
454       // TODO should we abort if we get an exception?
455       //
456     }
457         
458 end
459
460
461
462 /*
463 *
464
465 *
466 */
467 rule "${policyName}.EVENT.MANAGER.OPERATION.NOT_LOCKED.TIMEOUT"
468     timer (int: 5s 5s)
469     when
470         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
471         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
472         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
473         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
474         not ( TargetLock (requestID == $event.requestID) )
475     then
476
477     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
478     logger.info("{}: {}: event={} manager={} operation={}", 
479                 $params.getClosedLoopControlName(), drools.getRule().getName(),
480                 $event, $manager, $operation);
481     
482     //
483     // Need to ask for a Lock
484     //
485     LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
486     if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
487       logger.info("{}: {}: guard lock acquired={}", 
488                   $params.getClosedLoopControlName(), drools.getRule().getName(), 
489                   result.getB());
490       
491         //
492         // Insert into memory
493         //
494         insert(result.getB());
495     }
496     
497 end
498
499 /*
500 *
501 * Guard Permitted, let's send request to the actor.
502 *
503 */
504 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
505     when
506         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
507         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
508         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
509         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
510         $lock : TargetLock (requestID == $event.requestID)
511     then
512
513     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
514     logger.info("{}: {}: event={} manager={} operation={} lock={}", 
515                 $params.getClosedLoopControlName(), drools.getRule().getName(),
516                 $event, $manager, $operation, $lock);    
517
518     Object request = $operation.startOperation($event);
519     
520     if (request != null) {
521       logger.debug("{}: {}: starting operation ..", 
522                    $params.getClosedLoopControlName(), drools.getRule().getName());
523       //
524       // Tell interested parties we are performing this Operation
525       //
526       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
527       notification.notification = ControlLoopNotificationType.OPERATION;
528       notification.message = $operation.getOperationMessage();
529       notification.history = $operation.getHistory();
530       notification.from = "policy";
531       notification.policyName = drools.getRule().getName();
532       notification.policyScope = "${policyScope}";
533       notification.policyVersion = "${policyVersion}";
534       
535       PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
536       
537       switch ($operation.policy.getActor()){
538           
539           case "APPC":
540       
541               if (request instanceof Request) {
542                   PolicyEngine.manager.deliver("APPC-CL", request);
543               }
544               else if (request instanceof LCMRequestWrapper) {
545                   PolicyEngine.manager.deliver("APPC-LCM-READ", request);
546               }
547               break;
548           case "SO":
549               // at this point the AAI named query request should have already been made, the response recieved and used
550               // in the construction of the SO Request which is stored in operationRequest
551               
552               if(request instanceof SORequest) {
553                   // Call SO. The response will be inserted into memory once it's received 
554                   SOActorServiceProvider.sendRequest(drools.getWorkingMemory(), request);                        
555               }
556               break;
557           case "VFC":
558               if (request instanceof VFCRequest) {
559                   // Start VFC thread
560                   Thread t = new Thread(new VFCManager(drools.getWorkingMemory(), (VFCRequest)request));
561                   t.start();
562               }          
563               break;
564       }
565     } else {
566       //
567       // What happens if its null?
568       //
569       logger.warn("{}: {}: unexpected null operation request", 
570                   $params.getClosedLoopControlName(), 
571                   drools.getRule().getName());
572     }
573 end
574
575
576 /*
577 *
578 * We were able to acquire a lock so now let's ask Xacml Guard whether 
579 * we are allowed to proceed with the request to the actor.
580 *
581 */
582 rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
583     when
584         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
585         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
586         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
587         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID, getGuardApprovalStatus() == "NONE" )
588         $lock : TargetLock (requestID == $event.requestID)
589     then
590
591     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
592     logger.info("{}: {}: event={} manager={} operation={} lock={}", 
593                 $params.getClosedLoopControlName(), drools.getRule().getName(),
594                 $event, $manager, $operation, $lock);
595     
596     //
597     // Sending notification that we are about to query Guard ("DB write - start operation")
598     //
599     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
600     notification.notification = ControlLoopNotificationType.OPERATION;
601     notification.message = "Sending guard query for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe();
602     notification.history = $operation.getHistory();
603     notification.from = "policy";
604     notification.policyName = drools.getRule().getName();
605     notification.policyScope = "${policyScope}";
606     notification.policyVersion = "${policyVersion}";
607     
608     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
609         
610     //
611     // Now send Guard Request to XACML Guard. In order to bypass the call to Guard, 
612     // just change guardEnabled to false.
613     // 
614     // In order to use REST XACML, provide a URL instead of "" as a second argument 
615     // to the CallGuardTask() and set the first argument to null 
616     // (instead of XacmlPdpEngine).
617     //
618     
619     // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
620     boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngine.manager.getEnvironmentProperty("guard.disabled"));
621     
622     if(guardEnabled){
623     
624         Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
625                                                         drools.getWorkingMemory(),
626                                                         $event.closedLoopControlName,
627                                                         $operation.policy.getActor().toString(),
628                                                         $operation.policy.getRecipe(),
629                                                         $manager.getTargetInstance($operation.policy),
630                                                         //$event.target,
631                                                         $event.requestID.toString()
632                                                         ));
633         t.start();
634     }
635     else{
636         insert(new PolicyGuardResponse("Permit", $event.requestID, $operation.policy.getRecipe()));
637     }
638
639 end
640
641 //
642 // This rule will be triggered when a thread talking to the XACML Guard inserts a 
643 // guardResponse object into the working memory
644 //
645 rule "${policyName}.GUARD.RESPONSE"
646     when
647         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
648         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET )
649         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) 
650         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
651         $lock : TargetLock (requestID == $event.requestID)
652         $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
653         $guardResponse : PolicyGuardResponse(requestID == $event.requestID, $operation.policy.recipe == operation)
654     then
655
656     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
657     logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}", 
658                  $params.getClosedLoopControlName(), drools.getRule().getName(),
659                  $event, $manager, $operation, $lock, $opTimer, $guardResponse);
660         
661         
662     //we will permit the operation if there was no Guard for it
663     if("Indeterminate".equalsIgnoreCase($guardResponse.result)){
664         $guardResponse.result = "Permit";
665     }
666     
667     //
668     // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
669     //
670     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
671     notification.notification = ControlLoopNotificationType.OPERATION;
672     notification.message = "Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe() + " is " + $guardResponse.result;
673     notification.history = $operation.getHistory();
674     notification.from = "policy";
675     notification.policyName = drools.getRule().getName();
676     notification.policyScope = "${policyScope}";
677     notification.policyVersion = "${policyVersion}";
678     
679     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
680     
681     if("Permit".equalsIgnoreCase($guardResponse.result)){
682     
683         modify($operation){setGuardApprovalStatus($guardResponse.result)};
684     }
685     else {
686         //This is the Deny case
687         $operation.setOperationHasGuardDeny();
688         retract($opTimer);
689         retract($operation);
690         modify($manager) {finishOperation($operation)};
691     }
692     
693     retract($guardResponse);
694             
695 end
696
697 /*
698 *
699 * This rule responds to APPC Response Events
700 *
701 * I would have like to be consistent and write the Response like this:
702 * $response : Response( CommonHeader.RequestID == $onset.requestID )
703 *
704 * However, no compile error was given. But a runtime error was given. I think
705 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
706 *
707 */
708 rule "${policyName}.APPC.RESPONSE"
709     when
710         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
711         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) 
712         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
713         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
714         $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
715         $lock : TargetLock (requestID == $event.requestID)
716         $response : Response( getCommonHeader().RequestID == $event.requestID )
717     then
718
719     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
720     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
721     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
722                  $params.getClosedLoopControlName(), drools.getRule().getName(),
723                  $event, $manager, $operation, $lock, $opTimer, $response);
724     //
725     // Get the result of the operation
726     //
727     PolicyResult policyResult = $operation.onResponse($response);
728     if (policyResult != null) {
729         logger.debug("{}: {}: operation finished - result={}", 
730                     $params.getClosedLoopControlName(), drools.getRule().getName(),
731                     policyResult);
732         //
733         // This Operation has completed, construct a notification showing our results. (DB write - end operation)
734         //
735         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
736         notification.from = "policy";
737         notification.policyName = drools.getRule().getName();
738         notification.policyScope = "${policyScope}";
739         notification.policyVersion = "${policyVersion}";
740         notification.message = $operation.getOperationHistory();
741         notification.history = $operation.getHistory();
742         if (policyResult.equals(PolicyResult.SUCCESS)) {
743             notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS;
744             //
745             // Let interested parties know
746             //
747             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
748         } else {
749             notification.notification = ControlLoopNotificationType.OPERATION_FAILURE;
750             //
751             // Let interested parties know
752             //
753             PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
754         }
755         //
756         // Ensure the operation is complete
757         //
758         if ($operation.isOperationComplete() == true) {
759             //
760             // It is complete, remove it from memory
761             //
762             retract($operation);
763             //
764             // We must also retract the timer object
765             // NOTE: We could write a Rule to do this
766             //
767             retract($opTimer);
768             //
769             // Complete the operation
770             //
771             modify($manager) {finishOperation($operation)};
772         } else {
773             //
774             // Just doing this will kick off the LOCKED rule again
775             //
776             modify($operation) {};
777         }
778     } else {
779         //
780         // Its not finished yet (i.e. expecting more Response objects)
781         //
782         // Or possibly it is a leftover response that we timed the request out previously
783         //
784     }
785     //
786     // We are going to retract these objects from memory
787     //
788     retract($response);
789 end
790
791 /*
792 *
793 * The problem with Responses is that they don't have a controlLoopControlName
794 * field in them, so the only way to attach them is via RequestID. If we have multiple
795 * control loop .drl's loaded in the same container, we need to be sure the cleanup
796 * rules don't remove Responses for other control loops.
797 *
798 */
799 rule "${policyName}.APPC.RESPONSE.CLEANUP"
800     when
801         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
802         $response : Response($id : getCommonHeader().RequestID )
803         not ( VirtualControlLoopEvent( requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) 
804     then
805
806     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
807     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
808     logger.debug("{}: {}: orphan appc response={}", 
809                 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
810         
811     //
812     // Retract it
813     //
814     retract($response);
815 end
816
817 /*
818 *
819 * This rule responds to APPC Response Events using the new LCM interface provided by appc
820 *
821 */
822 rule "${policyName}.APPC.LCM.RESPONSE"
823     when
824         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
825         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) 
826         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
827         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
828         $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
829         $lock : TargetLock (requestID == $event.requestID)
830         $response : LCMResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.requestID )
831     then
832
833     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
834     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
835     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
836                 $params.getClosedLoopControlName(), drools.getRule().getName(),
837                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
838     
839     //
840     // Get the result of the operation
841     //
842     PolicyResult policyResult = $operation.onResponse($response);
843     if (policyResult != null) {
844       logger.debug("{}: {}: operation finished - result={}", 
845                   $params.getClosedLoopControlName(), drools.getRule().getName(),
846                   policyResult);
847       
848       //
849       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
850       //
851       VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
852       notification.from = "policy";
853       notification.policyName = drools.getRule().getName();
854       notification.policyScope = "${policyScope}";
855       notification.policyVersion = "${policyVersion}";
856       notification.message = $operation.getOperationHistory();
857       notification.history = $operation.getHistory();
858       if (policyResult.equals(PolicyResult.SUCCESS)) {
859           notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS;
860       } else {
861           notification.notification = ControlLoopNotificationType.OPERATION_FAILURE;
862       }
863       PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
864       //
865       // Ensure the operation is complete
866       //
867       if ($operation.isOperationComplete() == true) {
868           //
869           // It is complete, remove it from memory
870           //
871           retract($operation);
872           //
873           // We must also retract the timer object
874           // NOTE: We could write a Rule to do this
875           //
876           retract($opTimer);
877           //
878           // Complete the operation
879           //
880           modify($manager) {finishOperation($operation)};
881       } else {
882           //
883           // Just doing this will kick off the LOCKED rule again
884           //
885           modify($operation) {};
886       }
887     } else {
888         //
889         // Its not finished yet (i.e. expecting more Response objects)
890         //
891         // Or possibly it is a leftover response that we timed the request out previously
892         //
893     }
894     //
895     // We are going to retract these objects from memory
896     //
897     retract($response);
898 end
899
900 /*
901 *
902 * Clean Up any lingering LCM reponses
903 *
904 */
905 rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
906     when
907         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
908         $response : LCMResponseWrapper($id : getBody().getCommonHeader().getRequestId )
909         not ( VirtualControlLoopEvent( requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) 
910     then
911     
912     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
913     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
914     logger.debug("{}: {}: orphan appc response={}", 
915                 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
916     //
917     // Retract it
918     //
919     retract($response);
920 end
921
922 /*
923 *
924 * This rule responds to SO Response Events
925 *
926 */
927 rule "${policyName}.SO.RESPONSE"
928     when
929         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
930         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET )
931         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName )
932         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
933         $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
934         $lock : TargetLock (requestID == $event.requestID)
935         $response : SOResponse( requestReferences.requestId.toString() == $event.requestID.toString() )  
936     then
937         
938     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
939     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
940     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
941                 $params.getClosedLoopControlName(), drools.getRule().getName(),
942                 $event, $manager, $operation, $lock, $operation, $opTimer, $response);
943         
944     // Get the result of the operation
945     //
946     PolicyResult policyResult = $operation.onResponse($response);
947     if (policyResult != null) {
948         logger.debug("{}: {}: operation finished - result={}", 
949                     $params.getClosedLoopControlName(), drools.getRule().getName(),
950                     policyResult);
951       
952         //
953         // This Operation has completed, construct a notification showing our results
954         //
955         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
956         notification.from = "policy";
957         notification.policyName = drools.getRule().getName();
958         notification.policyScope = "${policyScope}";
959         notification.policyVersion = "${policyVersion}";
960         notification.message = $operation.getOperationHistory();
961         notification.history = $operation.getHistory();
962         if (policyResult.equals(PolicyResult.SUCCESS)) {
963             notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS;
964         } else {
965             notification.notification = ControlLoopNotificationType.OPERATION_FAILURE;
966
967         }
968         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
969         //
970         // Ensure the operation is complete
971         //
972         if ($operation.isOperationComplete() == true) {
973             //
974             // It is complete, remove it from memory
975             //
976             retract($operation);
977             //
978             // We must also retract the timer object
979             // NOTE: We could write a Rule to do this
980             //
981             retract($opTimer);
982             //
983             // Complete the operation
984             //
985             modify($manager) {finishOperation($operation)};
986         } else {
987             //
988             // Just doing this will kick off the LOCKED rule again
989             //
990             modify($operation) {};
991         }
992     } else {
993         //
994         // Its not finished yet (i.e. expecting more Response objects)
995         //
996         // Or possibly it is a leftover response that we timed the request out previously
997         //
998     }
999     //
1000     // We are going to retract these objects from memory
1001     //
1002     retract($response);
1003
1004 end
1005
1006 /*
1007 *
1008 * This rule responds to VFC Response Events
1009 *
1010 */
1011 rule "${policyName}.VFC.RESPONSE"
1012         when
1013                 $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1014                 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1015                 $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName )
1016                 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
1017                 $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() )
1018         $lock : TargetLock (requestID == $event.requestID)
1019                 $response : VFCResponse( requestId.toString() == $event.requestID.toString() )  
1020         then
1021                 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1022         logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1023         logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
1024                         $params.getClosedLoopControlName(), drools.getRule().getName(),
1025                         $event, $manager, $operation, $lock, $operation, $opTimer, $response);
1026                 
1027                 // Get the result of the operation
1028                 //
1029                 PolicyResult policyResult = $operation.onResponse($response);
1030                 if (policyResult != null) {
1031                         //
1032                         // This Operation has completed, construct a notification showing our results
1033                         //
1034                         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1035                         notification.from = "policy";
1036                         notification.policyName = drools.getRule().getName();
1037                         notification.policyScope = "${policyScope}";
1038                         notification.policyVersion = "${policyVersion}";
1039                         notification.message = $operation.getOperationHistory();
1040                         notification.history = $operation.getHistory();
1041                         //
1042                         // Ensure the operation is complete
1043                         //
1044                         if ($operation.isOperationComplete() == true) {
1045                                 //
1046                                 // It is complete, remove it from memory
1047                                 //
1048                                 retract($operation);
1049                                 //
1050                                 // We must also retract the timer object
1051                                 // NOTE: We could write a Rule to do this
1052                                 //
1053                                 retract($opTimer);
1054                                 //
1055                                 // Complete the operation
1056                                 //
1057                                 modify($manager) {finishOperation($operation)};
1058                         } else {
1059                                 //
1060                                 // Just doing this will kick off the LOCKED rule again
1061                                 //
1062                                 modify($operation) {};
1063                         }
1064                 } else {
1065                         //
1066                         // Its not finished yet (i.e. expecting more Response objects)
1067                         //
1068                         // Or possibly it is a leftover response that we timed the request out previously
1069                         //
1070                 }
1071                 //
1072                 // We are going to retract these objects from memory
1073                 //
1074                 retract($response);
1075
1076 end
1077
1078 /*
1079 *
1080 * This is the timer that manages the timeout for an individual operation.
1081 *
1082 */
1083 rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT"
1084     timer (expr: $to )
1085     when
1086         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1087         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1088         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
1089         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID )
1090         $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() )
1091         $lock : TargetLock (requestID == $event.requestID)
1092     then
1093     
1094     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1095     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1096     logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}", 
1097                 $params.getClosedLoopControlName(), drools.getRule().getName(),
1098                 $event, $manager, $operation, $lock, $operation, $opTimer);
1099     
1100     //
1101     // Tell it its timed out
1102     //
1103     $operation.setOperationHasTimedOut();
1104     //
1105     // Create a notification for it ("DB Write - end operation")
1106     //
1107     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1108     notification.from = "policy";
1109     notification.policyName = drools.getRule().getName();
1110     notification.policyScope = "${policyScope}";
1111     notification.policyVersion = "${policyVersion}";
1112     notification.notification = ControlLoopNotificationType.OPERATION_FAILURE;
1113     notification.message = $operation.getOperationHistory();
1114     notification.history = $operation.getHistory();
1115     //
1116     // Let interested parties know
1117     //
1118     PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1119     //
1120     // Get rid of the timer
1121     //
1122     retract($opTimer);
1123     //
1124     // Ensure the operation is complete
1125     //
1126     if ($operation.isOperationComplete() == true) {
1127         //
1128         // It is complete, remove it from memory
1129         //
1130         retract($operation);
1131         //
1132         // Complete the operation
1133         //
1134         modify($manager) {finishOperation($operation)};
1135     } else {
1136         //
1137         // Just doing this will kick off the LOCKED rule again
1138         //
1139         modify($operation) {};
1140     }
1141 end
1142
1143 /*
1144 *
1145 * This is the timer that manages the overall control loop timeout.
1146 *
1147 */
1148 rule "${policyName}.EVENT.MANAGER.TIMEOUT"
1149     timer (expr: $to )
1150     when
1151         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
1152         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
1153         $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID )
1154         $clTimer : ControlLoopTimer ( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString(), $to : getDelay() )
1155         $operations : LinkedList()
1156                         from collect( ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) )
1157         $opTimers : LinkedList()
1158                         from collect( OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) )
1159         $locks : LinkedList()
1160                         from collect( TargetLock (requestID == $event.requestID) )
1161     then
1162     
1163     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1164     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1165
1166     if ($operations == null) {
1167       logger.debug("{}: {}: event={} manager={} clTimer={} operations=0", 
1168                   $params.getClosedLoopControlName(), drools.getRule().getName(),
1169                   $event, $manager, $clTimer);
1170     } else {
1171       logger.debug("{}: {}: event={} manager={} clTimer={} operations={}", 
1172                   $params.getClosedLoopControlName(), drools.getRule().getName(),
1173                   $event, $manager, $clTimer, $operations.size());
1174     }
1175     //
1176     // Tell the Event Manager it has timed out
1177     //
1178     VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1179     if (notification != null) {
1180         notification.from = "policy";
1181         notification.policyName = drools.getRule().getName();
1182         notification.policyScope = "${policyScope}";
1183         notification.policyVersion = "${policyVersion}";
1184         //
1185         // Let interested parties know
1186         //
1187         PolicyEngine.manager.deliver("POLICY-CL-MGT", notification);
1188     }
1189     //
1190     // Retract EVERYTHING
1191     //
1192     retract($event);
1193     retract($manager);
1194     retract($clTimer);
1195     if ($operations != null && $operations.size() > 0) {
1196         Iterator<ControlLoopOperationManager> iter = $operations.iterator();
1197         while (iter.hasNext()) {
1198             ControlLoopOperationManager manager = iter.next();
1199             retract(manager);
1200         }
1201     }
1202     if ($opTimers != null && $opTimers.size() > 0) {
1203         Iterator<OperationTimer> iter = $opTimers.iterator();
1204         while (iter.hasNext()) {
1205             OperationTimer opTimer = iter.next();
1206             retract(opTimer);
1207         }
1208     }
1209     if ($locks != null && $locks.size() > 0) {
1210         Iterator<TargetLock> iter = $locks.iterator();
1211         while (iter.hasNext()) {
1212             TargetLock lock = iter.next();
1213             //
1214             // Ensure we release the lock
1215             //
1216             PolicyGuard.unlockTarget(lock);
1217             //
1218             //
1219             //
1220             retract(lock);
1221         }
1222     }
1223 end