2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2019 Bell Canada.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 * ============LICENSE_END=========================================================
22 package org.onap.policy.controlloop;
24 import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput;
25 import org.onap.policy.controlloop.params.ControlLoopParams;
26 import org.onap.policy.controlloop.VirtualControlLoopEvent;
27 import org.onap.policy.controlloop.VirtualControlLoopNotification;
28 import org.onap.policy.controlloop.ControlLoopEventStatus;
29 import org.onap.policy.controlloop.ControlLoopNotificationType;
30 import org.onap.policy.controlloop.ControlLoopLogger;
31 import org.onap.policy.controlloop.ControlLoopResponse;
32 import org.onap.policy.controlloop.policy.PolicyResult;
33 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
34 import org.onap.policy.controlloop.policy.Policy;
35 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
36 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
37 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
38 import org.onap.policy.controlloop.eventmanager.LockCallbackWorkingMemory;
39 import org.onap.policy.controlloop.utils.ControlLoopUtils;
40 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
41 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider;
42 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager;
43 import org.onap.policy.controlloop.actor.cds.constants.CdsActorConstants;
44 import org.onap.policy.aai.AaiNqResponseWrapper;
45 import org.onap.policy.aai.AaiCqResponse;
46 import org.onap.policy.appc.Request;
47 import org.onap.policy.appc.Response;
48 import org.onap.policy.appc.CommonHeader;
49 import org.onap.policy.appclcm.AppcLcmDmaapWrapper;
50 import org.onap.policy.cds.CdsResponse;
51 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
52 import org.onap.policy.cds.properties.CdsServerProperties;
53 import org.onap.policy.drools.utils.Pair;
54 import org.onap.policy.sdnr.PciRequestWrapper;
55 import org.onap.policy.sdnr.PciResponseWrapper;
56 import org.onap.policy.sdnr.PciRequest;
57 import org.onap.policy.sdnr.PciResponse;
58 import org.onap.policy.vfc.VfcRequest;
59 import org.onap.policy.vfc.VfcResponse;
60 import org.onap.policy.vfc.VfcManager;
61 import org.onap.policy.so.SoManager;
62 import org.onap.policy.so.SoRequest;
63 import org.onap.policy.so.SoResponseWrapper;
64 import org.onap.policy.sdnc.SdncRequest;
65 import org.onap.policy.sdnc.SdncManager;
66 import org.onap.policy.sdnc.SdncResponse;
67 import org.onap.policy.drools.core.lock.Lock;
68 import org.onap.policy.guard.PolicyGuardRequest;
69 import org.onap.policy.guard.PolicyGuardResponse;
70 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
71 import org.onap.policy.guard.PolicyGuardXacmlHelper;
72 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
74 import org.yaml.snakeyaml.Yaml;
75 import org.yaml.snakeyaml.constructor.Constructor;
77 import org.slf4j.LoggerFactory;
78 import org.slf4j.Logger;
80 import java.time.Instant;
81 import java.util.LinkedList;
82 import java.util.Iterator;
85 import org.onap.policy.drools.system.PolicyEngineConstants;
88 * This object is to provide support for timeouts
89 * due to a bug in drools' built-in timers
91 declare ControlLoopTimer
92 closedLoopControlName : String
96 //timerType is the type of timer: either "ClosedLoop" or "Operation"
102 * Called when the ControlLoopParams object has been inserted into working memory from the BRMSGW.
107 $params : ControlLoopParams()
110 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
111 logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "."
112 + drools.getRule().getName(), $params.getControlLoopYaml());
117 * Called when a Tosca Policy is present.
120 rule "NEW.TOSCA.POLICY"
122 $policy : ToscaPolicy()
125 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
126 logger.info("{}: [{}|{}|{}|{}]: CONTENT: {}", drools.getRule().getName(),
127 $policy.getType(), $policy.getTypeVersion(), $policy.getName(),
128 $policy.getVersion(), $policy);
130 ControlLoopParams params = ControlLoopUtils.toControlLoopParams($policy);
131 if (params != null) {
137 * Remove Control Loop Parameters.
141 $params : ControlLoopParams( $policyName : getPolicyName(), $policyVersion : getPolicyVersion() )
142 not ( ToscaPolicy( getName() == $policyName, getVersion() == $policyVersion ) )
145 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
146 logger.info("{}: [{}|{}|{}]", drools.getRule().getName(),
147 $params.getPolicyScope(), $params.getPolicyName(), $params.getPolicyVersion());
154 * This rule responds to DCAE Events where there is no manager yet. Either it is
155 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
160 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
161 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
162 not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
163 requestId == $event.getRequestId() ) )
166 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
167 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
172 // Check the event, because we need it to not be null when
173 // we create the ControlLoopEventManager. The ControlLoopEventManager
174 // will do extra syntax checking as well check if the closed loop is disabled.
176 if ($event.getRequestId() == null) {
177 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
178 notification.setNotification(ControlLoopNotificationType.REJECTED);
179 notification.setFrom("policy");
180 notification.setMessage("Missing requestId");
181 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
182 notification.setPolicyScope($params.getPolicyScope());
183 notification.setPolicyVersion($params.getPolicyVersion());
186 // Let interested parties know
188 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
191 // Retract it from memory
194 } else if ($event.getClosedLoopEventStatus() != ControlLoopEventStatus.ONSET) {
195 throw new ControlLoopException($event.getClosedLoopEventStatus() + " received with no prior onset");
198 // Create an EventManager
200 ControlLoopEventManager manager = new ControlLoopEventManager($clName, $event.getRequestId());
202 // Determine if EventManager can actively process the event
203 // (i.e. syntax, is_closed_loop_disabled checks etc.)
205 VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
206 notification.setFrom("pdp-0001-controller=controlloop"); // Engine.getInstanceName()
207 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
208 notification.setPolicyScope($params.getPolicyScope());
209 notification.setPolicyVersion($params.getPolicyVersion());
211 // Are we actively pursuing this event?
213 if (notification.getNotification() == ControlLoopNotificationType.ACTIVE) {
215 // Insert Event Manager into memory, this will now kick off processing.
219 // Let interested parties know
221 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
223 // Setup the Overall Control Loop timer
225 ControlLoopTimer clTimer = new ControlLoopTimer();
226 clTimer.setTimerType("ClosedLoop");
227 clTimer.setClosedLoopControlName($event.getClosedLoopControlName());
228 clTimer.setRequestId($event.getRequestId().toString());
229 clTimer.setDelay(manager.getControlLoopTimeout(1500) + "s");
236 // Let interested parties know
238 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
240 // Retract it from memory
246 // Now that the manager is inserted into Drools working memory, we'll wait for
247 // another rule to fire in order to continue processing. This way we can also
248 // then screen for additional ONSET and ABATED events for this RequestId.
251 } catch (Exception e) {
252 logger.warn("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName(), e);
254 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
255 notification.setNotification(ControlLoopNotificationType.REJECTED);
256 notification.setMessage("Exception occurred: " + e.getMessage());
257 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
258 notification.setPolicyScope($params.getPolicyScope());
259 notification.setPolicyVersion($params.getPolicyVersion());
263 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
273 * This rule happens when we got a valid ONSET, closed loop is enabled and an Event Manager
274 * is now created. We can start processing the yaml specification via the Event Manager.
279 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
280 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
281 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
282 requestId == $event.getRequestId() )
283 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
284 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
287 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
288 logger.info("{}: {}: event={} manager={} clTimer={}",
289 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
290 $event, $manager, $clTimer);
294 // Check which event this is.
296 ControlLoopEventManager.NewEventStatus eventStatus = $manager.onNewEvent($event);
298 // Check what kind of event this is
300 if (eventStatus == NewEventStatus.SUBSEQUENT_ONSET) {
302 // We don't care about subsequent onsets
304 logger.info("{}: {}: subsequent onset",
305 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
309 if (eventStatus == NewEventStatus.SYNTAX_ERROR) {
311 // Ignore any bad syntax events
313 logger.warn("{}: {}: syntax error",
314 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
319 // We only want the initial ONSET event in memory,
320 // all the other events need to be retracted to support
321 // cleanup and avoid the other rules being fired for this event.
323 if (eventStatus != NewEventStatus.FIRST_ONSET) {
324 logger.warn("{}: {}: no first onset",
325 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
329 logger.debug("{}: {}: target={}", $clName,
330 $params.getPolicyName() + "." + drools.getRule().getName(), $event.getTarget());
332 // Now start seeing if we need to process this event
336 // Check if this is a Final Event
338 VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
341 if (notification != null) {
343 // Its final, but are we waiting for abatement?
345 if ($manager.getNumAbatements() > 0) {
346 logger.info("{}: {}: abatement received for {}. Closing the control loop",
347 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
348 $event.getRequestId());
349 notification.setFrom("policy");
350 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
351 notification.setPolicyScope($params.getPolicyScope());
352 notification.setPolicyVersion($params.getPolicyVersion());
354 // In this case, we are done
356 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
360 Lock lock = $manager.unlockCurrentOperation();
362 logger.debug("{}: {}.{}: retracting lock={}", $clName,
363 $params.getPolicyName(), drools.getRule().getName(), lock);
367 // Retract everything from memory
369 logger.info("{}: {}: retracting onset, manager, and timer",
370 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
372 retract($manager.getOnsetEvent());
374 // don't retract manager, etc. - a clean-up rule will do that
377 // TODO - what if we get subsequent Events for this RequestId?
378 // By default, it will all start over again. May be confusing for Ruby.
379 // Or, we could track this and then subsequently ignore the events
383 // Check whether we need to wait for abatement
385 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
386 logger.info("{}: {}: waiting for abatement ..",
387 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
389 logger.info("{}: {}: no abatement expect for {}. Closing the control loop",
390 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
391 $event.getRequestId());
393 notification.setFrom("policy");
394 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
395 notification.setPolicyScope($params.getPolicyScope());
396 notification.setPolicyVersion($params.getPolicyVersion());
399 // In this case, we are done
401 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
405 Lock lock = $manager.unlockCurrentOperation();
407 logger.debug("{}: {}.{}: retracting lock={}", $clName,
408 $params.getPolicyName(), drools.getRule().getName(), lock);
412 // Retract everything from memory
414 logger.info("{}: {}: retracting onset, manager, and timer",
415 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
417 retract($manager.getOnsetEvent());
419 // don't retract manager, etc. - a clean-up rule will do that
424 // NOT final, so let's ask for the next operation
426 ControlLoopOperationManager operation = $manager.processControlLoop();
427 if (operation != null) {
429 // Let's ask for a lock right away
431 logger.info("{}: {}.{}: requesting lock for operation={}",
432 $clName, $params.getPolicyName(), drools.getRule().getName(),
435 Pair<Lock,Lock> oldNew = $manager.lockCurrentOperation(
436 new LockCallbackWorkingMemory($params.getClosedLoopControlName(), drools.getWorkingMemory()));
437 if(oldNew.first() != null) {
438 logger.debug("{}: {}.{}: retracting lock={}", $clName,
439 $params.getPolicyName(), drools.getRule().getName(), oldNew.first());
440 retract(oldNew.first());
442 if(oldNew.second() != null) {
443 logger.debug("{}: {}.{}: inserting lock={}", $clName,
444 $params.getPolicyName(), drools.getRule().getName(), oldNew.second());
445 insert(oldNew.second());
449 // insert the operation into memory
454 // insert operation timeout object
456 ControlLoopTimer opTimer = new ControlLoopTimer();
457 opTimer.setTimerType("Operation");
458 opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
459 opTimer.setRequestId($event.getRequestId().toString());
460 Integer timeout = operation.getOperationTimeout();
461 opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
466 // Probably waiting for abatement
468 logger.info("{}: {}: no operation, probably waiting for abatement",
469 $clName, $params.getPolicyName() + "." + drools.getRule().getName());
472 } catch (Exception e) {
473 logger.warn("{}: {}: unexpected",
475 $params.getPolicyName() + "." + drools.getRule().getName(), e);
477 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
478 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
479 notification.setMessage(e.getMessage());
480 notification.setFrom("policy");
481 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
482 notification.setPolicyScope($params.getPolicyScope());
483 notification.setPolicyVersion($params.getPolicyVersion());
485 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
489 // don't retract manager, etc. - a clean-up rule will do that
499 rule "EVENT.MANAGER.OPERATION.LOCK.DENIED"
501 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
502 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
503 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
504 requestId == $event.getRequestId() )
505 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
506 onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
507 $lock : Lock (ownerKey == $event.getRequestId().toString(), isUnavailable())
510 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
511 logger.info("{}: {}.{}: event={} manager={} operation={} lock={}",
512 $clName, $params.getPolicyName(), drools.getRule().getName(),
513 $event, $manager, $operation, $lock);
515 logger.debug("The target resource {} is already processing", $event.getAai().get($event.getTarget()));
516 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
517 notification.setNotification(ControlLoopNotificationType.REJECTED);
518 notification.setMessage("The target " + $event.getAai().get($event.getTarget()) + " is already locked");
519 notification.setFrom("policy");
520 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
521 notification.setPolicyScope($params.getPolicyScope());
522 notification.setPolicyVersion($params.getPolicyVersion());
524 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
528 // don't retract manager, etc. - a clean-up rule will do that
533 * Guard Permitted, let's send request to the actor.
536 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
538 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
539 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
540 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
541 requestId == $event.getRequestId() )
542 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
543 onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
544 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
545 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
548 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
549 logger.info("{}: {}: event={} manager={} operation={}",
550 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
551 $event, $manager, $operation);
553 Object request = null;
554 boolean caughtException = false;
557 request = $operation.startOperation($event);
559 if (request != null) {
560 logger.debug("{}: {}: starting operation ..",
562 $params.getPolicyName() + "." + drools.getRule().getName());
564 // Tell interested parties we are performing this Operation
566 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
567 notification.setNotification(ControlLoopNotificationType.OPERATION);
568 notification.setMessage($operation.getOperationMessage());
569 notification.setHistory($operation.getHistory());
570 notification.setFrom("policy");
571 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
572 notification.setPolicyScope($params.getPolicyScope());
573 notification.setPolicyVersion($params.getPolicyVersion());
575 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
577 switch ($operation.policy.getActor()){
581 if (request instanceof Request) {
582 PolicyEngineConstants.getManager().deliver("APPC-CL", request);
584 else if (request instanceof AppcLcmDmaapWrapper) {
585 PolicyEngineConstants.getManager().deliver("APPC-LCM-READ", request);
589 // at this point the AAI named query request should have already been made, the response
590 // recieved and used in the construction of the SO Request which is stored in operationRequest
592 if(request instanceof SoRequest) {
593 // Call SO. The response will be inserted into memory once it's received
594 class mySoCallback implements SoManager.SoCallback {
595 public void onSoResponseWrapper(SoResponseWrapper wrapper) {
596 drools.getWorkingMemory().insert(wrapper);
599 SoActorServiceProvider.sendRequest($event.getRequestId().toString(),
602 PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
603 PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
604 PolicyEngineConstants.getManager().getEnvironmentProperty("so.password"));
608 if (request instanceof VfcRequest) {
609 class myVfcCallback implements VfcManager.VfcCallback {
611 public void onResponse(VfcResponse responseError) {
612 drools.getWorkingMemory().insert(responseError);
616 Thread t = new Thread(new VfcManager(new myVfcCallback(),
618 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.url"),
619 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
620 PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password")));
625 if (request instanceof PciRequestWrapper) {
626 PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
631 if (request instanceof SdncRequest) {
632 class mySdncCallback implements SdncManager.SdncCallback {
633 public void onCallback(SdncResponse response) {
634 drools.getWorkingMemory().insert(response);
638 Thread t = new Thread(new SdncManager(new mySdncCallback(),
639 (SdncRequest)request,
640 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
641 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
642 PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
649 if(request instanceof ExecutionServiceInput) {
651 // Instantiate cds actor, service manager and grpc properties
653 CdsActorServiceProvider cdsActor = new CdsActorServiceProvider();
654 CdsActorServiceProvider.CdsActorServiceManager cdsActorServiceManager = cdsActor.new CdsActorServiceManager();
656 CdsServerProperties props = new CdsServerProperties();
657 props.setHost(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcHost"));
658 props.setPort(Integer.parseInt(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcPort")));
659 props.setUsername(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcUsername"));
660 props.setPassword(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcPassword"));
661 props.setTimeout(Integer.parseInt(PolicyEngineConstants.getManager().getEnvironmentProperty("cds.grpcTimeout")));
663 // Send cds grpc request
664 try (CdsProcessorGrpcClient client = new CdsProcessorGrpcClient(cdsActorServiceManager, props)) {
665 CdsResponse response =
666 cdsActorServiceManager.sendRequestToCds(client, props, (ExecutionServiceInput) request);
667 logger.info("CDS response: {}", response);
675 // What happens if its null?
677 logger.warn("{}: {}: unexpected null operation request",
679 $params.getPolicyName() + "." + drools.getRule().getName());
680 if ("SO".equals($operation.policy.getActor())) {
683 modify($manager) {finishOperation($operation)};
685 else if ("vfc".equalsIgnoreCase($operation.policy.getActor())) {
688 modify($manager) {finishOperation($operation)};
690 else if ("sdnc".equalsIgnoreCase($operation.policy.getActor())) {
693 modify($manager) {finishOperation($operation)};
697 } catch (Exception e) {
698 String msg = e.getMessage();
699 logger.warn("{}: {}: operation={}: AAI failure: {}",
701 $params.getPolicyName() + "." + drools.getRule().getName(),
703 $operation.setOperationHasException(msg);
705 if(request != null) {
707 // Create a notification for it ("DB Write - end operation")
709 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
710 notification.setFrom("policy");
711 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
712 notification.setPolicyScope($params.getPolicyScope());
713 notification.setPolicyVersion($params.getPolicyVersion());
714 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
715 notification.setMessage($operation.getOperationHistory());
716 notification.setHistory($operation.getHistory());
718 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
723 caughtException = true;
726 // Having the modify statement in the catch clause doesn't work for whatever reason
727 if (caughtException) {
728 modify($manager) {finishOperation($operation)};
735 * We were able to acquire a lock so now let's ask Xacml Guard whether
736 * we are allowed to proceed with the request to the actor.
739 rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
741 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
742 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
743 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
744 requestId == $event.getRequestId() )
745 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
746 onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
747 $lock : Lock (ownerKey == $event.getRequestId().toString(), isActive())
750 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
751 logger.info("{}: {}: event={} manager={} operation={} lock={}",
752 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
753 $event, $manager, $operation, $lock);
756 // Sending notification that we are about to query Guard ("DB write - start operation")
758 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
759 notification.setNotification(ControlLoopNotificationType.OPERATION);
760 notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
761 + $operation.policy.getRecipe());
762 notification.setHistory($operation.getHistory());
763 notification.setFrom("policy");
764 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
765 notification.setPolicyScope($params.getPolicyScope());
766 notification.setPolicyVersion($params.getPolicyVersion());
768 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
771 // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
772 // just change guardEnabled to false.
774 // In order to use REST XACML, provide a URL instead of "" as a second argument
775 // to the CallGuardTask() and set the first argument to null
776 // (instead of XacmlPdpEngine).
779 // NOTE: The environment properties uses "guard.disabled" but the boolean is guardEnabled
780 boolean guardEnabled = "false".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("guard.disabled"));
781 boolean cqEnabled = "true".equalsIgnoreCase(PolicyEngineConstants.getManager().getEnvironmentProperty("aai.customQuery"));
785 Thread t = new Thread(new org.onap.policy.guard.CallGuardTask(
786 drools.getWorkingMemory(),
787 $event.getClosedLoopControlName(),
788 $operation.policy.getActor().toString(),
789 $operation.policy.getRecipe(),
790 $operation.getTargetEntity(),
791 $event.getRequestId().toString(),
794 AaiNqResponseWrapper resp = $manager.getNqVserverFromAai();
795 return(resp == null ? null : resp.countVfModules());
798 AaiCqResponse resp_cq = $manager.getCqResponse($event);
799 if (resp_cq == null){
802 String custId = $operation.policy.getTarget().getModelCustomizationId();
803 String invId = $operation.policy.getTarget().getModelInvariantId();
804 String verId = $operation.policy.getTarget().getModelVersionId();
805 return resp_cq.getVfModuleCount(custId, invId, verId);
807 } catch (Exception e){
808 logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
816 insert(new PolicyGuardResponse("Permit", $event.getRequestId(), $operation.policy.getRecipe()));
822 // This rule will be triggered when a thread talking to the XACML Guard inserts a
823 // guardResponse object into the working memory
825 rule "GUARD.RESPONSE"
827 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
828 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
829 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
830 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
831 requestId == $event.getRequestId() )
832 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
833 onset.getRequestId() == $event.getRequestId() )
834 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
835 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
836 $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
839 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
840 logger.info("{}: {}: event={} manager={} operation={} opTimer={} guardResponse={}",
841 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
842 $event, $manager, $operation, $opTimer, $guardResponse);
845 //we will permit the operation if there was no Guard for it
846 if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
847 $guardResponse.setResult("Permit");
851 // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
853 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
854 notification.setNotification(ControlLoopNotificationType.OPERATION);
855 notification.setMessage("Guard result for " + $operation.policy.getActor() + " " + $operation.policy.getRecipe()
856 + " is " + $guardResponse.getResult());
857 notification.setHistory($operation.getHistory());
858 notification.setFrom("policy");
859 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
860 notification.setPolicyScope($params.getPolicyScope());
861 notification.setPolicyVersion($params.getPolicyVersion());
863 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
865 if("Permit".equalsIgnoreCase($guardResponse.getResult())){
867 modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
870 //This is the Deny case
871 $operation.startOperation($event);
872 $operation.setOperationHasGuardDeny();
875 modify($manager) {finishOperation($operation)};
878 retract($guardResponse);
884 * This rule responds to APPC Response Events
886 * I would have like to be consistent and write the Response like this:
887 * $response : Response( CommonHeader.RequestId == $onset.getRequestId() )
889 * However, no compile error was given. But a runtime error was given. I think
890 * because drools is confused between the classname CommonHeader vs the property CommonHeader.
895 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
896 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
897 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
898 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
899 requestId == $event.getRequestId() )
900 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
901 onset.getRequestId() == $event.getRequestId() )
902 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
903 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
904 $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
907 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
908 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
909 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
910 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
911 $event, $manager, $operation, $opTimer, $response);
913 // Get the result of the operation
915 PolicyResult policyResult = $operation.onResponse($response);
916 if (policyResult != null) {
917 logger.debug("{}: {}: operation finished - result={}",
918 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
921 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
923 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
924 notification.setFrom("policy");
925 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
926 notification.setPolicyScope($params.getPolicyScope());
927 notification.setPolicyVersion($params.getPolicyVersion());
928 notification.setMessage($operation.getOperationHistory());
929 notification.setHistory($operation.getHistory());
930 if (policyResult.equals(PolicyResult.SUCCESS)) {
931 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
933 // Let interested parties know
935 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
937 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
939 // Let interested parties know
941 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
944 // Ensure the operation is complete
946 if ($operation.isOperationComplete() == true) {
948 // It is complete, remove it from memory
952 // We must also retract the timer object
953 // NOTE: We could write a Rule to do this
957 // Complete the operation
959 modify($manager) {finishOperation($operation)};
962 // Just doing this will kick off the LOCKED rule again
964 modify($operation) {};
968 // Its not finished yet (i.e. expecting more Response objects)
970 // Or possibly it is a leftover response that we timed the request out previously
974 // We are going to retract these objects from memory
981 * The problem with Responses is that they don't have a controlLoopControlName
982 * field in them, so the only way to attach them is via RequestId. If we have multiple
983 * control loop .drl's loaded in the same container, we need to be sure the cleanup
984 * rules don't remove Responses for other control loops.
987 rule "APPC.RESPONSE.CLEANUP"
989 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
990 $response : Response($id : getCommonHeader().RequestId )
991 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
994 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
995 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
996 logger.debug("{}: {}: orphan appc response={}",
997 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
1007 * This rule responds to APPC Response Events using the new LCM interface provided by appc
1010 rule "APPC.LCM.RESPONSE"
1012 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1013 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1014 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1015 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1016 requestId == $event.getRequestId() )
1017 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1018 onset.getRequestId() == $event.getRequestId() )
1019 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1020 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1021 $response : AppcLcmDmaapWrapper( getBody().getOutput().getCommonHeader().getRequestId() == $event.getRequestId() )
1024 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1025 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1026 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1027 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1028 $event, $manager, $operation, $operation, $opTimer, $response);
1031 // Get the result of the operation
1033 PolicyResult policyResult = $operation.onResponse($response);
1034 if (policyResult != null) {
1035 logger.debug("{}: {}: operation finished - result={}",
1036 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1040 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1042 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1043 notification.setFrom("policy");
1044 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1045 notification.setPolicyScope($params.getPolicyScope());
1046 notification.setPolicyVersion($params.getPolicyVersion());
1047 notification.setMessage($operation.getOperationHistory());
1048 notification.setHistory($operation.getHistory());
1049 if (policyResult.equals(PolicyResult.SUCCESS)) {
1050 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1052 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1054 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1056 // Ensure the operation is complete
1058 if ($operation.isOperationComplete() == true) {
1060 // It is complete, remove it from memory
1062 retract($operation);
1064 // We must also retract the timer object
1065 // NOTE: We could write a Rule to do this
1069 // Complete the operation
1071 modify($manager) {finishOperation($operation)};
1074 // Just doing this will kick off the LOCKED rule again
1076 modify($operation) {};
1080 // Its not finished yet (i.e. expecting more Response objects)
1082 // Or possibly it is a leftover response that we timed the request out previously
1086 // We are going to retract these objects from memory
1093 * Clean Up any lingering LCM reponses
1096 rule "APPC.LCM.RESPONSE.CLEANUP"
1098 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1099 $response : AppcLcmDmaapWrapper($id : getBody().getOutput().getCommonHeader().getRequestId() )
1100 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1103 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1104 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1105 logger.debug("{}: {}: orphan appc response={}",
1106 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);
1115 * This rule responds to SO Response Events
1120 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1121 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1122 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1123 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1124 requestId == $event.getRequestId() )
1125 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1126 onset.getRequestId() == $event.getRequestId() )
1127 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1128 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1129 $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
1132 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1133 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1134 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1135 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1136 $event, $manager, $operation, $operation, $opTimer, $response);
1138 // Get the result of the operation
1140 PolicyResult policyResult = $operation.onResponse($response);
1141 if (policyResult != null) {
1142 logger.debug("{}: {}: operation finished - result={}",
1143 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1147 // This Operation has completed, construct a notification showing our results
1149 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1150 notification.setFrom("policy");
1151 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1152 notification.setPolicyScope($params.getPolicyScope());
1153 notification.setPolicyVersion($params.getPolicyVersion());
1154 notification.setMessage($operation.getOperationHistory());
1155 notification.setHistory($operation.getHistory());
1156 if (policyResult.equals(PolicyResult.SUCCESS)) {
1157 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1159 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1162 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1164 // Ensure the operation is complete
1166 if ($operation.isOperationComplete() == true) {
1168 // It is complete, remove it from memory
1170 retract($operation);
1172 // We must also retract the timer object
1173 // NOTE: We could write a Rule to do this
1177 // Complete the operation
1179 modify($manager) {finishOperation($operation)};
1182 // Just doing this will kick off the LOCKED rule again
1184 modify($operation) {};
1188 // Its not finished yet (i.e. expecting more Response objects)
1190 // Or possibly it is a leftover response that we timed the request out previously
1194 // We are going to retract these objects from memory
1202 * This rule responds to VFC Response Events
1207 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1208 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1209 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1210 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1211 requestId == $event.getRequestId() )
1212 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1213 onset.getRequestId() == $event.getRequestId() )
1214 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1215 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1216 $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
1218 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1219 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1220 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1221 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1222 $event, $manager, $operation, $operation, $opTimer, $response);
1224 // Get the result of the operation
1226 PolicyResult policyResult = $operation.onResponse($response);
1227 if (policyResult != null) {
1229 // This Operation has completed, construct a notification showing our results
1231 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1232 notification.setFrom("policy");
1233 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1234 notification.setPolicyScope($params.getPolicyScope());
1235 notification.setPolicyVersion($params.getPolicyVersion());
1236 notification.setMessage($operation.getOperationHistory());
1237 notification.setHistory($operation.getHistory());
1239 // Ensure the operation is complete
1241 if ($operation.isOperationComplete() == true) {
1243 // It is complete, remove it from memory
1245 retract($operation);
1247 // We must also retract the timer object
1248 // NOTE: We could write a Rule to do this
1252 // Complete the operation
1254 modify($manager) {finishOperation($operation)};
1257 // Just doing this will kick off the LOCKED rule again
1259 modify($operation) {};
1263 // Its not finished yet (i.e. expecting more Response objects)
1265 // Or possibly it is a leftover response that we timed the request out previously
1269 // We are going to retract these objects from memory
1277 * This rule responds to SDNC Response Events
1280 rule "SDNC.RESPONSE"
1282 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1283 $event : VirtualControlLoopEvent( closedLoopControlName == $clName, closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1284 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestId == $event.getRequestId() )
1285 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId() )
1286 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1287 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1288 $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
1290 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1291 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1292 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1293 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1294 $event, $manager, $operation, $operation, $opTimer, $response);
1296 // Get the result of the operation
1298 PolicyResult policyResult = $operation.onResponse($response);
1299 if (policyResult != null) {
1301 // This Operation has completed, construct a notification showing our results
1303 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1304 notification.setFrom("policy");
1305 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1306 notification.setPolicyScope($params.getPolicyScope());
1307 notification.setPolicyVersion($params.getPolicyVersion());
1308 notification.setMessage($operation.getOperationHistory());
1309 notification.setHistory($operation.getHistory());
1311 // Ensure the operation is complete
1313 if ($operation.isOperationComplete()) {
1315 // It is complete, remove it from memory
1317 retract($operation);
1319 // We must also retract the timer object
1320 // NOTE: We could write a Rule to do this
1324 // Complete the operation
1326 modify($manager) {finishOperation($operation)};
1329 // Just doing this will kick off the LOCKED rule again
1331 modify($operation) {};
1335 // Its not finished yet (i.e. expecting more Response objects)
1337 // Or possibly it is a leftover response that we timed the request out previously
1341 // We are going to retract these objects from memory
1349 * This rule responds to CDS Response Events
1351 rule "${policyName}.CDS.RESPONSE"
1353 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1354 $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
1355 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1356 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1357 requestId == $event.getRequestId() )
1358 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1359 onset.getRequestId() == $event.getRequestId() )
1360 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1361 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1362 $response : CdsResponse( requestId == $event.getRequestId().toString() )
1366 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1367 logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
1368 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1369 $params.getClosedLoopControlName(), drools.getRule().getName(),
1370 $event, $manager, $operation, $operation, $opTimer, $response);
1372 // Get the result of the operation
1373 PolicyResult policyResult = $operation.onResponse($response);
1375 if (policyResult != null) {
1376 logger.debug("{}: {}: operation finished - result={}",
1377 $params.getClosedLoopControlName(), drools.getRule().getName(),
1380 // The operation has completed, construct a notification showing our results
1381 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1382 notification.setFrom("policy");
1383 notification.setPolicyName(drools.getRule().getName());
1384 notification.setPolicyScope($params.getPolicyScope());
1385 notification.setPolicyVersion($params.getPolicyVersion());
1386 notification.setMessage($operation.getOperationHistory());
1387 notification.setHistory($operation.getHistory());
1388 notification.setNotification(
1389 ($response != null && CdsActorConstants.SUCCESS.equals($response.getStatus()))
1390 ? ControlLoopNotificationType.OPERATION_SUCCESS : ControlLoopNotificationType.OPERATION_FAILURE);
1392 // Send the notification
1393 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1395 // Ensure the operation is complete
1396 if ($operation.isOperationComplete()) {
1398 // It is complete, remove it from memory
1399 retract($operation);
1401 // We must also retract the timer object
1402 // NOTE: We could write a Rule to do this
1405 // Complete the operation
1406 modify($manager) {finishOperation($operation)};
1409 // Just doing this will kick off the LOCKED rule again
1410 modify($operation) {};
1413 // Its not finished yet (i.e. expecting more Response objects)
1414 // Or possibly it is a leftover response that we timed the request out previously
1416 "policyResult is null"
1417 + "\nIt's not finished yet (i.e. expecting more Response objects)"
1418 + "\nOr possibly it is a leftover response that we timed the request out previously");
1421 // We are going to retract these objects from memory
1429 * This manages a single timer.
1430 * Due to a bug in the drools code, the drools timer needed to be split from most of the objects in the when clause
1434 timer (expr: $timeout)
1436 $timer : ControlLoopTimer($timeout : delay, !expired)
1438 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1439 logger.info("This is TIMER.FIRED");
1440 modify($timer){setExpired(true)};
1445 * This is the timer that manages the timeout for an individual operation.
1448 rule "EVENT.MANAGER.OPERATION.TIMEOUT"
1450 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1451 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1452 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1453 requestId == $event.getRequestId() )
1454 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1455 onset.getRequestId() == $event.getRequestId() )
1456 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1457 requestId == $event.getRequestId().toString(), timerType == "Operation", expired )
1460 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1461 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1462 logger.debug("{}: {}: event={} manager={} operation={} opTimer={}",
1463 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1464 $event, $manager, $operation, $operation, $opTimer);
1467 // Tell it its timed out
1469 $operation.setOperationHasTimedOut();
1471 // Create a notification for it ("DB Write - end operation")
1473 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1474 notification.setFrom("policy");
1475 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1476 notification.setPolicyScope($params.getPolicyScope());
1477 notification.setPolicyVersion($params.getPolicyVersion());
1478 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1479 notification.setMessage($operation.getOperationHistory());
1480 notification.setHistory($operation.getHistory());
1482 // Let interested parties know
1484 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1486 // Get rid of the timer
1490 // Ensure the operation is complete
1492 if ($operation.isOperationComplete() == true) {
1494 // It is complete, remove it from memory
1496 retract($operation);
1498 // Complete the operation
1500 modify($manager) {finishOperation($operation)};
1503 // Just doing this will kick off the LOCKED rule again
1505 modify($operation) {};
1511 * This is the timer that manages the overall control loop timeout.
1514 rule "EVENT.MANAGER.TIMEOUT"
1516 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1517 $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
1518 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1519 requestId == $event.getRequestId() )
1520 $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1521 requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", expired )
1524 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1525 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1527 logger.debug("{}: {}: event={}",
1528 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1531 // Tell the Event Manager it has timed out
1533 VirtualControlLoopNotification notification = $manager.setControlLoopTimedOut();
1534 if (notification != null) {
1535 notification.setFrom("policy");
1536 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1537 notification.setPolicyScope($params.getPolicyScope());
1538 notification.setPolicyVersion($params.getPolicyVersion());
1540 // Let interested parties know
1542 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1545 // Retract the event
1552 * This rule cleans up the manager and other objects after an event has
1556 rule "EVENT.MANAGER.CLEANUP"
1558 $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
1559 $operations : LinkedList()
1560 from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
1561 onset.getRequestId() == $requestId ) )
1562 $timers : LinkedList()
1563 from collect( ControlLoopTimer( closedLoopControlName == $clName,
1564 requestId == $requestId.toString() ) )
1565 not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
1568 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1569 logger.info("{}: {}", $clName, drools.getRule().getName());
1571 logger.debug("{}: {}: manager={} timers={} operations={}",
1572 $clName, drools.getRule().getName(),
1573 $manager, $timers.size(), $operations.size());
1576 // Retract lock by invoking unlock()
1578 Lock lock = $manager.unlockCurrentOperation();
1584 // Retract EVERYTHING
1588 for(Object manager: $operations) {
1589 retract((ControlLoopOperationManager) manager);
1591 for(Object timer: $timers) {
1592 retract((ControlLoopTimer) timer);
1598 * This rule will clean up any rogue onsets where there is no
1599 * ControlLoopParams object corresponding to the onset event.
1602 rule "EVENT.CLEANUP"
1604 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1605 not ( ControlLoopParams( getClosedLoopControlName() == $clName) )
1608 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1609 logger.info("{}: {}", $clName, drools.getRule().getName());
1610 logger.debug("{}: {}: orphan onset event={}",
1611 $clName, drools.getRule().getName(), $event);
1618 * This rule responds to SDNR Response Events.
1621 rule "SDNR.RESPONSE"
1623 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1624 $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
1625 closedLoopEventStatus == ControlLoopEventStatus.ONSET )
1626 $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
1627 requestId == $event.getRequestId() )
1628 $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
1629 onset.getRequestId() == $event.getRequestId() )
1630 $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
1631 requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
1632 $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
1635 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1636 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1637 logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
1638 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1639 $event, $manager, $operation, $operation, $opTimer, $response);
1642 // Get the result of the operation
1644 PolicyResult policyResult = $operation.onResponse($response);
1645 if (policyResult != null) {
1646 logger.debug("{}: {}: operation finished - result={}",
1647 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
1651 // This Operation has completed, construct a notification showing our results. (DB write - end operation)
1653 VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
1654 notification.setFrom("policy");
1655 notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
1656 notification.setPolicyScope($params.getPolicyScope());
1657 notification.setPolicyVersion($params.getPolicyVersion());
1658 notification.setMessage($operation.getOperationHistory());
1659 notification.setHistory($operation.getHistory());
1660 if (policyResult.equals(PolicyResult.SUCCESS)) {
1661 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
1663 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
1665 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
1667 ControlLoopResponse clResponse = $operation.getControlLoopResponse($response, $event);
1668 PolicyEngineConstants.getManager().deliver("DCAE_CL_RSP", clResponse);
1670 // Ensure the operation is complete
1672 if ($operation.isOperationComplete() == true) {
1674 // It is complete, remove it from memory
1676 retract($operation);
1678 // We must also retract the timer object
1679 // NOTE: We could write a Rule to do this
1683 // Complete the operation
1685 modify($manager) {finishOperation($operation)};
1688 // Just doing this will kick off the LOCKED rule again
1690 modify($operation) {};
1694 // Its not finished yet (i.e. expecting more Response objects)
1696 // Or possibly it is a leftover response that we timed the request out previously
1700 // We are going to retract these objects from memory
1707 * Clean Up any lingering SDNR reponses.
1710 rule "SDNR.RESPONSE.CLEANUP"
1712 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
1713 $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
1714 not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
1717 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1718 logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
1719 logger.debug("{}: {}: orphan sdnr response={}",
1720 $clName, $params.getPolicyName() + "." + drools.getRule().getName(), $id);