2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-2022 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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.controlloop;
23 import java.time.Instant;
24 import java.util.Collections;
25 import java.util.stream.Collectors;
26 import org.onap.policy.controlloop.CanonicalOnset;
27 import org.onap.policy.controlloop.VirtualControlLoopEvent;
28 import org.onap.policy.controlloop.VirtualControlLoopNotification;
29 import org.onap.policy.controlloop.ControlLoopNotificationType;
30 import org.onap.policy.controlloop.actor.xacml.XacmlActor;
31 import org.onap.policy.controlloop.actorserviceprovider.Operation;
32 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
33 import org.onap.policy.controlloop.actorserviceprovider.OperationFinalResult;
34 import org.onap.policy.controlloop.actorserviceprovider.OperationProperties;
35 import org.onap.policy.controlloop.actorserviceprovider.OperationResult;
36 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
37 import org.onap.policy.controlloop.eventmanager.ActorConstants;
38 import org.onap.policy.controlloop.eventmanager.Step;
39 import org.onap.policy.controlloop.utils.ControlLoopUtils;
40 import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager;
41 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithSteps.State;
42 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithOutcome.OperationOutcome2;
43 import org.onap.policy.controlloop.eventmanager.ClEventManagerWithEvent.NewEventStatus;
44 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
45 import org.onap.policy.controlloop.eventmanager.EventManagerServices;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
48 import org.slf4j.LoggerFactory;
49 import org.slf4j.Logger;
51 import org.onap.policy.drools.system.PolicyEngineConstants;
55 * Called at initial start-up, to create the event services that will be used by all
56 * event managers in this rule engine instance.
58 rule "CREATE.EVENT.SERVICES"
60 not (EventManagerServices())
63 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
64 logger.info("{}", drools.getRule().getName());
67 insert(new EventManagerServices("event-manager"));
69 } catch(RuntimeException e) {
70 logger.warn("{}: cannot create event services", drools.getRule().getName(), e);
76 * Called when the ControlLoopParams object has been inserted into working memory from the PAP.
81 $params : ControlLoopParams()
84 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
85 logger.info("{}: {} : TOSCA-POLICY=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "."
86 + drools.getRule().getName(), $params.getToscaPolicy());
91 * Called when a Tosca Policy is present.
94 rule "NEW.TOSCA.POLICY"
96 $policy : ToscaPolicy()
99 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
100 logger.info("{}: [{}|{}|{}|{}]: CONTENT: {}", drools.getRule().getName(),
101 $policy.getType(), $policy.getTypeVersion(), $policy.getName(),
102 $policy.getVersion(), $policy);
104 ControlLoopParams params = ControlLoopUtils.toControlLoopParams($policy);
105 if (params != null) {
111 * Remove Control Loop Parameters.
115 $params : ControlLoopParams( $policyName : getPolicyName(), $policyVersion : getPolicyVersion() )
116 not ( ToscaPolicy( getName() == $policyName, getVersion() == $policyVersion ) )
119 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
120 logger.info("{}: [{}|{}|{}]", drools.getRule().getName(),
121 $params.getPolicyScope(), $params.getPolicyName(), $params.getPolicyVersion());
128 * This rule responds to DCAE Events where there is no manager yet. Either it is
129 * the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled)
134 $params : ControlLoopParams( $clName : getClosedLoopControlName() )
135 $event : CanonicalOnset( closedLoopControlName == $clName )
136 $services : EventManagerServices()
137 not ( UsecasesEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
138 getEvent() == $event ) )
141 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
142 logger.info("{}: {}.{}: event={}",
143 $clName, $params.getPolicyName(), drools.getRule().getName(),
146 // Retract the event from memory; it will be managed by the manager from now on
150 VirtualControlLoopNotification notification = null;
154 // Check the event, because we need it to not be null when
155 // we create the UsecasesEventManager. The UsecasesEventManager
156 // will do extra syntax checking as well as check if the closed loop is disabled.
158 if ($event.getRequestId() == null) {
159 notification = new VirtualControlLoopNotification($event);
160 notification.setNotification(ControlLoopNotificationType.REJECTED);
161 notification.setFrom("policy");
162 notification.setMessage("Missing requestId");
163 notification.setPolicyScope(drools.getRule().getName());
164 notification.setPolicyName($params.getPolicyName());
165 notification.setPolicyVersion($params.getPolicyVersion());
168 UsecasesEventManager manager =
169 new UsecasesEventManager($services, $params, $event, drools.getWorkingMemory());
172 // load the first policy/step
175 if (manager.getSteps().isEmpty()) {
176 // no steps implies no policies, thus go straight to DONE state
177 manager.setState(State.DONE);
179 manager.setAccepted(true);
181 notification = manager.makeNotification();
182 notification.setNotification(ControlLoopNotificationType.ACTIVE);
183 notification.setPolicyScope(drools.getRule().getName());
184 notification.setPolicyName($params.getPolicyName());
185 notification.setPolicyVersion($params.getPolicyVersion());
188 // Note: the notification will be generated lazily
189 manager.setState(State.POLICY_LOADED);
192 } catch(Exception e) {
197 } catch (Exception e) {
198 logger.warn("{}: {}.{}: error starting manager", $clName, $params.getPolicyName(),
199 drools.getRule().getName(), e);
200 notification = new VirtualControlLoopNotification($event);
201 notification.setNotification(ControlLoopNotificationType.REJECTED);
202 notification.setMessage("Exception occurred: " + e.getMessage());
203 notification.setPolicyScope(drools.getRule().getName());
204 notification.setPolicyName($params.getPolicyName());
205 notification.setPolicyVersion($params.getPolicyVersion());
208 // Generate notification
211 if (notification != null) {
212 PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
215 } catch(RuntimeException e) {
216 logger.warn("{}: {}.{}: event={} exception generating notification",
217 $clName, $params.getPolicyName(), drools.getRule().getName(),
224 * This rule fires when we get a subsequent event.
227 rule "EVENT.MANAGER.NEW.EVENT"
229 $event : VirtualControlLoopEvent( )
230 $manager : UsecasesEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
231 getEvent() == $event )
234 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
235 logger.info("{}: {}.{}: event={} manager={}",
236 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
239 // Remove the event from memory
244 // Check what kind of event this is
246 switch($manager.onNewEvent($event)) {
249 // Ignore any bad syntax events
251 logger.warn("{}: {}.{}: syntax error",
252 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName());
255 case FIRST_ABATEMENT:
256 case SUBSEQUENT_ABATEMENT:
258 // TODO: handle the abatement. Currently, it's just discarded.
260 logger.info("{}: {}.{}: abatement",
261 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName());
265 case SUBSEQUENT_ONSET:
268 // We don't care about subsequent onsets
270 logger.warn("{}: {}.{}: subsequent onset",
271 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName());
278 * All steps have been executed, load the next policy.
281 rule "EVENT.MANAGER.LOAD.NEXT.POLICY"
283 $manager : UsecasesEventManager(
285 getState() == State.POLICY_LOADED,
286 getSteps().isEmpty() )
289 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
290 logger.info("{}: {}.{}: manager={}",
291 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
295 $manager.loadNextPolicy($manager.getResult());
297 if ($manager.getSteps().isEmpty()) {
298 // no steps - must be the final policy
299 $manager.setState(State.DONE);
302 } catch(RuntimeException e) {
303 logger.warn("{}: {}.{}: manager={} exception loading next policy",
304 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
306 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to load next policy");
314 * Policy loaded, identify any preprocessor steps that need to be run first.
317 rule "EVENT.MANAGER.PREPROCESS"
319 $manager : UsecasesEventManager(
321 getState() == State.POLICY_LOADED,
322 $step : getSteps().peek(),
324 !$step.isPreprocessed() )
327 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
328 logger.info("{}: {}.{}: {} manager={}",
329 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
334 * Load any preprocessor steps.
336 * Note: this will not change the state of the manager, but it may change the
339 $step.setPreprocessed(true);
340 $manager.loadPreprocessorSteps();
342 } catch(RuntimeException e) {
343 logger.warn("{}: {}.{}: manager={} exception loading preprocessor steps",
344 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
346 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to load preprocessing steps");
354 * Accepts the event, when ready to execute a step of interest. Does not change the
355 * state of the manager, leaving that to be done by rule "EVENT.MANAGER.EXECUTE.STEP".
358 rule "EVENT.MANAGER.ACCEPT"
361 $manager : UsecasesEventManager(
364 getState() == State.POLICY_LOADED,
365 $step : getSteps().peek(),
367 $step.isPreprocessed(),
368 $step.acceptsEvent() )
371 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
372 logger.info("{}: {}.{}: manager={}",
373 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
377 $manager.setAccepted(true);
379 VirtualControlLoopNotification notification = $manager.makeNotification();
380 notification.setNotification(ControlLoopNotificationType.ACTIVE);
381 notification.setPolicyScope(drools.getRule().getName());
382 notification.setPolicyName($manager.getPolicyName());
383 notification.setPolicyVersion($manager.getPolicyVersion());
384 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
386 } catch(RuntimeException e) {
387 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
388 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
390 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to accept the event");
398 * Ready to execute the step.
401 rule "EVENT.MANAGER.EXECUTE.STEP"
403 $manager : UsecasesEventManager(
405 getState() == State.POLICY_LOADED,
406 $step : getSteps().peek(),
408 $step.isPreprocessed() )
411 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
412 logger.info("{}: {}.{}: {} manager={}",
413 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
418 $step.setProperties();
420 boolean guardDisabled = "true".equalsIgnoreCase(
421 PolicyEngineConstants.getManager().getEnvironmentProperty(
422 ControlLoopEventManager.GUARD_DISABLED_PROPERTY));
424 if (guardDisabled && XacmlActor.NAME.equals($step.getActorName())) {
425 // guard is disabled - just enqueue a "SUCCESS" (i.e., "Permit")
426 OperationOutcome outcome = $step.getParams().makeOutcome();
427 outcome.setStart(Instant.now());
428 outcome.setEnd(outcome.getStart());
430 $manager.getOutcomes().add(outcome);
431 $manager.setState(State.AWAITING_OUTCOME);
433 } else if ($manager.executeStep()) {
434 $manager.setState(State.AWAITING_OUTCOME);
437 // this step is no longer necessary - try the next one
441 } catch(RuntimeException e) {
442 logger.warn("{}: {}.{}: manager={} exception executing a step",
443 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
445 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to execute the next step");
453 * Generate SDNR notification. Does not discard the outcome from the queue, leaving it to be
454 * handled by rule "EVENT.MANAGER.PROCESS.OUTCOME".
457 rule "EVENT.MANAGER.GENERATE.SDNR.NOTIFICATION"
458 // this should fire BEFORE the "EVENT.MANAGER.PROCESS.OUTCOME" rule
461 $manager : UsecasesEventManager(
463 getState() == State.AWAITING_OUTCOME,
464 $outcome : getOutcomes().peek(),
466 $outcome.getEnd() != null,
468 $step : getSteps().peek(),
469 "SDNR".equals($step.getActorName()),
470 $outcome.isFor("SDNR", $step.getOperationName()) )
473 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
474 logger.info("{}: {}.{}: {} manager={}",
475 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
479 ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome);
480 $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName());
482 } catch(RuntimeException e) {
483 logger.warn("{}: {}.{}: manager={} exception generating SDNR Response notification",
484 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
491 * Process a GUARD outcome. Does not discard the outcome from the queue, leaving it to be
492 * handled by rule "EVENT.MANAGER.PROCESS.OUTCOME".
495 rule "EVENT.MANAGER.PROCESS.GUARD.OUTCOME"
498 $manager : UsecasesEventManager(
500 getState() == State.AWAITING_OUTCOME,
501 $outcome : getOutcomes().peek(),
504 $step : getSteps().peek(),
505 XacmlActor.NAME.equals($step.getActorName()),
506 $outcome.isFor($step.getActorName(), $step.getOperationName()) )
509 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
510 logger.info("{}: {}.{}: {} manager={}",
511 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
515 VirtualControlLoopNotification notification = $manager.makeNotification();
516 notification.setNotification(ControlLoopNotificationType.OPERATION);
517 notification.setPolicyScope(drools.getRule().getName());
518 notification.setPolicyName($manager.getPolicyName());
519 notification.setPolicyVersion($manager.getPolicyVersion());
520 notification.setHistory(Collections.emptyList());
522 // get actor/operation name from the policy step, not from the guard step
523 Step step2 = $step.getParentStep();
525 if ($outcome.getEnd() == null) {
526 // it's a "start" operation
527 notification.setMessage("Sending guard query for " + step2.getActorName() + " " + step2.getOperationName());
529 } else if ($outcome.getResult() == OperationResult.SUCCESS) {
530 notification.setMessage("Guard result for " + step2.getActorName() + " " + step2.getOperationName()
534 notification.setMessage("Guard result for " + step2.getActorName() + " " + step2.getOperationName()
538 $manager.deliver("POLICY-CL-MGT", notification, "GUARD notification", drools.getRule().getName());
540 } catch(RuntimeException e) {
541 logger.warn("{}: {}.{}: manager={} exception generating GUARD notification",
542 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
549 * Process an outcome when the policy's operation starts.
552 rule "EVENT.MANAGER.PROCESS.POLICY.STARTED"
554 $manager : UsecasesEventManager(
556 getState() == State.AWAITING_OUTCOME,
557 $outcome : getOutcomes().peek(),
559 $outcome.getEnd() == null,
560 $step : getSteps().peek(),
561 $step.isPolicyStep(),
562 $outcome.isFor($step.getActorName(), $step.getOperationName()) )
565 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
566 logger.info("{}: {}.{}: {} manager={}",
567 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
571 $manager.getOutcomes().remove();
573 // it's a "start" operation for the step
574 $manager.bumpAttempts();
576 $manager.addToHistory($outcome);
577 $manager.storeInDataBase($manager.getPartialHistory().peekLast());
579 VirtualControlLoopNotification notification = $manager.makeNotification();
580 notification.setNotification(ControlLoopNotificationType.OPERATION);
581 notification.setPolicyScope(drools.getRule().getName());
582 notification.setPolicyName($manager.getPolicyName());
583 notification.setPolicyVersion($manager.getPolicyVersion());
584 notification.setHistory(Collections.emptyList());
585 notification.setMessage($manager.getOperationMessage());
587 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
589 } catch(RuntimeException e) {
590 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
591 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
593 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'start' outcome");
601 * Process an outcome when an arbitrary Preprocessor step starts.
604 rule "EVENT.MANAGER.PROCESS.PREPROCESSOR.STARTED"
606 $manager : UsecasesEventManager(
608 getState() == State.AWAITING_OUTCOME,
609 $outcome : getOutcomes().peek(),
611 $outcome.getEnd() == null,
612 $step : getSteps().peek(),
613 !$step.isPolicyStep(),
614 $outcome.isFor($step.getActorName(), $step.getOperationName()) )
617 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
618 logger.info("{}: {}.{}: {} manager={}",
619 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
623 $manager.getOutcomes().remove();
625 // it's a "start" operation for the step
626 $manager.bumpAttempts();
628 } catch(RuntimeException e) {
629 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
630 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
632 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle 'start' outcome");
640 * Process an outcome when the policy's operation succeeds.
643 rule "EVENT.MANAGER.PROCESS.POLICY.SUCCESS"
645 $manager : UsecasesEventManager(
647 getState() == State.AWAITING_OUTCOME,
648 $outcome : getOutcomes().peek(),
650 $outcome.getEnd() != null,
651 $outcome.getResult() == OperationResult.SUCCESS,
652 $step : getSteps().peek(),
653 $step.isPolicyStep(),
654 $outcome.isFor($step.getActorName(), $step.getOperationName()) )
657 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
658 logger.info("{}: {}.{}: {} manager={}",
659 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
663 $manager.getOutcomes().remove();
665 // let the step record the response that's contained within the outcome
666 $step.success($outcome);
668 $manager.addToHistory($outcome);
669 $manager.storeInDataBase($manager.getPartialHistory().peekLast());
671 $manager.setResult($outcome.getResult());
673 VirtualControlLoopNotification notification = $manager.makeNotification();
674 notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS);
675 notification.setPolicyScope(drools.getRule().getName());
676 notification.setPolicyName($manager.getPolicyName());
677 notification.setPolicyVersion($manager.getPolicyVersion());
678 notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation)
679 .collect(Collectors.toList()));
681 // this step is complete - discard it
682 $manager.getSteps().remove();
684 $manager.setState(State.POLICY_LOADED);
686 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
688 } catch(RuntimeException e) {
689 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
690 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
692 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'success' outcome");
700 * Process a final failure outcome, when the event has been accepted.
703 rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.ACCEPTED"
705 $manager : UsecasesEventManager(
708 getState() == State.AWAITING_OUTCOME,
709 $outcome : getOutcomes().peek(),
712 $outcome.getEnd() != null,
713 $outcome.isFinalOutcome(),
714 $outcome.getResult() != OperationResult.SUCCESS,
715 $step : getSteps().peek() )
718 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
719 logger.info("{}: {}.{}: {} manager={}",
720 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
724 $manager.getOutcomes().remove();
726 if (!$outcome.isFor($step.getActorName(), $step.getOperationName())) {
727 $outcome.setResult(OperationResult.FAILURE_GUARD);
728 $outcome.setMessage("Operation denied by " + $outcome.getActor());
731 // final failure for this policy
732 $manager.addToHistory($outcome);
733 $manager.storeInDataBase($manager.getPartialHistory().peekLast());
735 $manager.setResult($outcome.getResult());
737 VirtualControlLoopNotification notification = $manager.makeNotification();
738 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
739 notification.setPolicyScope(drools.getRule().getName());
740 notification.setPolicyName($manager.getPolicyName());
741 notification.setPolicyVersion($manager.getPolicyVersion());
742 notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation)
743 .collect(Collectors.toList()));
745 // trigger move to the next policy - clear all steps
746 $manager.getSteps().clear();
747 $manager.setState(State.POLICY_LOADED);
749 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
751 } catch(RuntimeException e) {
752 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
753 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
755 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'failure' outcome");
763 * Process a final failure outcome, when the event has NOT been accepted. This typically
764 * occurs when an A&AI query fails BEFORE the first lock has been requested (and thus
765 * before the first policy's operation has been started).
768 rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.REJECTED"
770 $manager : UsecasesEventManager(
773 getState() == State.AWAITING_OUTCOME,
774 $outcome : getOutcomes().peek(),
777 $outcome.getEnd() != null,
778 $outcome.isFinalOutcome(),
779 $outcome.getResult() != OperationResult.SUCCESS,
780 $step : getSteps().peek() )
783 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
784 logger.info("{}: {}.{}: {} manager={}",
785 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
791 // final failure for this policy
792 $manager.addToHistory($outcome);
794 $manager.setResult($outcome.getResult());
796 VirtualControlLoopNotification notification = $manager.makeNotification();
797 notification.setNotification(ControlLoopNotificationType.REJECTED);
798 notification.setPolicyScope(drools.getRule().getName());
799 notification.setPolicyName($manager.getPolicyName());
800 notification.setPolicyVersion($manager.getPolicyVersion());
801 notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation)
802 .collect(Collectors.toList()));
804 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
806 } catch(RuntimeException e) {
807 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
808 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
810 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to reject event");
818 * Process an outcome when the policy's operation fails.
821 rule "EVENT.MANAGER.PROCESS.POLICY.FAILURE"
823 $manager : UsecasesEventManager(
825 getState() == State.AWAITING_OUTCOME,
826 $outcome : getOutcomes().peek(),
829 $outcome.getEnd() != null,
830 !$outcome.isFinalOutcome(),
831 $outcome.getResult() != OperationResult.SUCCESS,
832 $step : getSteps().peek(),
833 $step.isPolicyStep(),
834 $outcome.isFor($step.getActorName(), $step.getOperationName()) )
837 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
838 logger.info("{}: {}.{}: {} manager={}",
839 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
843 // not a final failure, thus it will be retried automatically
845 $manager.getOutcomes().remove();
847 // do NOT invoke manager.setResult()
849 $manager.addToHistory($outcome);
850 $manager.storeInDataBase($manager.getPartialHistory().peekLast());
852 VirtualControlLoopNotification notification = $manager.makeNotification();
853 notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
854 notification.setPolicyScope(drools.getRule().getName());
855 notification.setPolicyName($manager.getPolicyName());
856 notification.setPolicyVersion($manager.getPolicyVersion());
858 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
860 } catch(RuntimeException e) {
861 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
862 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
864 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'failure' outcome");
872 * Discard an outcome that was not handled by any other rule.
875 rule "EVENT.MANAGER.DISCARD.OUTCOME"
878 $manager : UsecasesEventManager(
880 getState() == State.AWAITING_OUTCOME,
881 $outcome : getOutcomes().peek(),
883 $step : getSteps().peek() )
886 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
887 logger.info("{}: {}.{}: {} {} manager={}",
888 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
889 $step, $outcome.getResult(), $manager);
892 $manager.getOutcomes().remove();
894 if ($outcome.getEnd() != null && $outcome.isFor($step.getActorName(), $step.getOperationName())) {
895 // it's a completion for the step
897 // let the step record the response that's contained within the outcome
898 if ($outcome.getResult() == OperationResult.SUCCESS) {
899 $step.success($outcome);
902 // this step is complete - discard it
903 $manager.getSteps().remove();
905 $manager.setState(State.POLICY_LOADED);
908 } catch(RuntimeException e) {
909 logger.warn("{}: {}.{}: manager={} exception processing operation outcome",
910 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
912 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle outcome");
920 * Abort processing. This can happen in any state (once the manager has been started).
923 rule "EVENT.MANAGER.ABORT"
925 $manager : UsecasesEventManager(
927 getState() != State.DONE,
928 $outcome : getOutcomes().peek(),
931 $step : getSteps().peek() )
934 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
935 logger.info("{}: {}.{}: {} manager={}",
936 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
940 // determine the final message
942 switch ($outcome.getActor()) {
943 case ActorConstants.CL_TIMEOUT_ACTOR:
944 msg = "Control Loop timed out";
946 case ActorConstants.LOCK_ACTOR:
947 msg = "Target Lock was lost";
950 msg = "Processing aborted by " + $outcome.getActor();
954 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE, msg);
956 if ($step != null && "SDNR".equals($step.getActorName())
957 && $outcome.isFor($step.getActorName(), $step.getOperationName())) {
959 // aborted while processing the SDNR step - generate a notification
960 ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome);
961 $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName());
965 $outcome.setActor($step.getActorName());
966 $outcome.setOperation($step.getOperationName());
968 $manager.addToHistory($outcome);
969 $manager.storeInDataBase($manager.getPartialHistory().peekLast());
972 } catch(RuntimeException e) {
973 logger.warn("{}: {}.{}: manager={} exception handling ABORT outcome",
974 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
976 $manager.abort(State.DONE, OperationFinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle ABORT");
984 * Done processing. Arriving here implies that the event has been accepted.
987 rule "EVENT.MANAGER.FINAL"
989 $manager : UsecasesEventManager(
990 !isActive() || getState() == State.DONE )
993 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
994 logger.info("{}: {}.{}: manager={}",
995 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
1001 VirtualControlLoopNotification notification = $manager.makeNotification();
1002 notification.setPolicyScope(drools.getRule().getName());
1003 notification.setPolicyName($manager.getPolicyName());
1004 notification.setPolicyVersion($manager.getPolicyVersion());
1005 notification.setHistory($manager.getFullHistory().stream().map(OperationOutcome2::getClOperation)
1006 .collect(Collectors.toList()));
1008 OperationFinalResult finalResult = $manager.getFinalResult();
1009 if (finalResult == null) {
1010 finalResult = ($manager.isActive() ? OperationFinalResult.FINAL_SUCCESS : OperationFinalResult.FINAL_FAILURE);
1013 switch (finalResult) {
1014 case FINAL_FAILURE_EXCEPTION:
1015 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
1016 notification.setMessage("Exception in processing closed loop");
1019 notification.setNotification(ControlLoopNotificationType.FINAL_SUCCESS);
1021 case FINAL_OPENLOOP:
1022 notification.setNotification(ControlLoopNotificationType.FINAL_OPENLOOP);
1026 notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE);
1030 if ($manager.getFinalMessage() != null) {
1031 notification.setMessage($manager.getFinalMessage());
1034 $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName());
1036 } catch(RuntimeException e) {
1037 logger.warn("{}: {}.{}: manager={} exception generating final notification",
1038 $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(),
1047 * This rule will clean up any rogue events where there is no
1048 * ControlLoopParams object corresponding to the onset event.
1051 rule "EVENT.CLEANUP"
1054 $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
1057 Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
1058 logger.info("{}: {}", $clName, drools.getRule().getName());
1059 logger.debug("{}: {}: orphan event={}",
1060 $clName, drools.getRule().getName(), $event);
1062 // Retract the event
1069 * At this point, it appears that if we prevent the rules from getting messages from
1070 * topics, then that will also prevent the actors from getting them. So the following
1071 * rules are here just to discard those messages.
1073 * These have a higher salience so the objects are removed before the "FINAL" message
1074 * is processed, so that the junit test can assume things are done once they see the
1075 * "FINAL" message. Otherwise, tests might fail sporadically.
1078 rule "APPC.Response.CLEANUP"
1081 $msg : org.onap.policy.appc.Response( )
1086 rule "APPC.Request.CLEANUP"
1089 $msg : org.onap.policy.appc.Request( )
1094 rule "APPC-LCM.Response.CLEANUP"
1097 $msg : org.onap.policy.appclcm.AppcLcmDmaapWrapper( )
1102 rule "SDNR.Response.CLEANUP"
1105 $msg : org.onap.policy.sdnr.PciResponseWrapper( )