From ffdf210ad1e3f18dcc612e2587ed6d3742ab1e24 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Thu, 30 Jul 2020 18:05:02 -0400 Subject: Move java code to rules Added new usecases rules and feature. Updates per review comments: - kmodule.xml(s) Issue-ID: POLICY-2748 Change-Id: I2f5cb05a4269f98a3b0a778730434955f0919b4a Signed-off-by: Jim Hahn --- .../src/main/resources/META-INF/kmodule.xml | 2 +- controlloop/common/controller-usecases/pom.xml | 11 + .../src/main/resources/META-INF/kmodule.xml | 26 + .../src/main/resources/usecases.drl | 1053 ++++++++++++++++++++ .../org/onap/policy/controlloop/UsecasesTest.java | 119 +++ .../src/test/resources/usecases.pom | 30 + .../common/feature-controlloop-usecases/pom.xml | 114 +++ .../src/assembly/assemble_zip.xml | 85 ++ .../feature/config/logback-include-usecases.xml | 56 ++ .../feature/config/usecases-controller.properties | 64 ++ .../feature/usecases/UsecasesFeature.java | 43 + ...p.policy.drools.features.PolicyEngineFeatureApi | 1 + .../feature/usecases/UsecasesFeatureTest.java | 31 + controlloop/common/pom.xml | 1 + .../src/test/resources/META-INF/kmodule.xml | 2 +- .../docker-controlloop/src/main/docker/Dockerfile | 4 + 16 files changed, 1640 insertions(+), 2 deletions(-) create mode 100644 controlloop/common/controller-usecases/src/main/resources/META-INF/kmodule.xml create mode 100644 controlloop/common/controller-usecases/src/main/resources/usecases.drl create mode 100644 controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java create mode 100644 controlloop/common/controller-usecases/src/test/resources/usecases.pom create mode 100644 controlloop/common/feature-controlloop-usecases/pom.xml create mode 100644 controlloop/common/feature-controlloop-usecases/src/assembly/assemble_zip.xml create mode 100644 controlloop/common/feature-controlloop-usecases/src/main/feature/config/logback-include-usecases.xml create mode 100644 controlloop/common/feature-controlloop-usecases/src/main/feature/config/usecases-controller.properties create mode 100644 controlloop/common/feature-controlloop-usecases/src/main/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeature.java create mode 100644 controlloop/common/feature-controlloop-usecases/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi create mode 100644 controlloop/common/feature-controlloop-usecases/src/test/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeatureTest.java diff --git a/controlloop/common/controller-frankfurt/src/main/resources/META-INF/kmodule.xml b/controlloop/common/controller-frankfurt/src/main/resources/META-INF/kmodule.xml index 011d7ef2f..cc39944a0 100644 --- a/controlloop/common/controller-frankfurt/src/main/resources/META-INF/kmodule.xml +++ b/controlloop/common/controller-frankfurt/src/main/resources/META-INF/kmodule.xml @@ -20,7 +20,7 @@ --> + packages="org.onap.policy.controlloop"> diff --git a/controlloop/common/controller-usecases/pom.xml b/controlloop/common/controller-usecases/pom.xml index e99077a47..6f55131e9 100644 --- a/controlloop/common/controller-usecases/pom.xml +++ b/controlloop/common/controller-usecases/pom.xml @@ -29,10 +29,21 @@ controller-usecases + kjar ${project.artifactId} Usecases Experimental Controller + + + + org.kie + kie-maven-plugin + true + + + + org.onap.policy.models.policy-models-interactions.model-impl diff --git a/controlloop/common/controller-usecases/src/main/resources/META-INF/kmodule.xml b/controlloop/common/controller-usecases/src/main/resources/META-INF/kmodule.xml new file mode 100644 index 000000000..7db705b2b --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/resources/META-INF/kmodule.xml @@ -0,0 +1,26 @@ + + + + + + + diff --git a/controlloop/common/controller-usecases/src/main/resources/usecases.drl b/controlloop/common/controller-usecases/src/main/resources/usecases.drl new file mode 100644 index 000000000..439512cf5 --- /dev/null +++ b/controlloop/common/controller-usecases/src/main/resources/usecases.drl @@ -0,0 +1,1053 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop; + +import java.util.Collections; +import java.util.stream.Collectors; +import org.onap.policy.controlloop.CanonicalOnset; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.actor.aai.AaiActor; +import org.onap.policy.controlloop.actor.aai.AaiGetPnfOperation; +import org.onap.policy.controlloop.actor.aai.AaiGetTenantOperation; +import org.onap.policy.controlloop.actor.guard.GuardActor; +import org.onap.policy.controlloop.actor.guard.DecisionOperation; +import org.onap.policy.controlloop.actorserviceprovider.Operation; +import org.onap.policy.controlloop.actorserviceprovider.OperationProperties; +import org.onap.policy.controlloop.drl.legacy.ControlLoopParams; +import org.onap.policy.controlloop.eventmanager.ActorConstants; +import org.onap.policy.controlloop.eventmanager.Step; +import org.onap.policy.controlloop.policy.Policy; +import org.onap.policy.controlloop.policy.FinalResult; +import org.onap.policy.controlloop.policy.PolicyResult; +import org.onap.policy.controlloop.utils.ControlLoopUtils; +import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager; +import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager.State; +import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager.NewEventStatus; +import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager.OperationOutcome2; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; + +import org.slf4j.LoggerFactory; +import org.slf4j.Logger; + +import org.onap.policy.drools.system.PolicyEngineConstants; + +/* +* +* Called when the ControlLoopParams object has been inserted into working memory from the PAP. +* +*/ +rule "INSERT.PARAMS" + when + $params : ControlLoopParams() + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {} : TOSCA-POLICY=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "." + + drools.getRule().getName(), $params.getToscaPolicy()); +end + +/* +* +* Called when a Tosca Policy is present. +* +*/ +rule "NEW.TOSCA.POLICY" + when + $policy : ToscaPolicy() + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: [{}|{}|{}|{}]: CONTENT: {}", drools.getRule().getName(), + $policy.getType(), $policy.getTypeVersion(), $policy.getName(), + $policy.getVersion(), $policy); + + ControlLoopParams params = ControlLoopUtils.toControlLoopParams($policy); + if (params != null) { + insert(params); + } +end + +/* + * Remove Control Loop Parameters. + */ +rule "REMOVE.PARAMS" + when + $params : ControlLoopParams( $policyName : getPolicyName(), $policyVersion : getPolicyVersion() ) + not ( ToscaPolicy( getName() == $policyName, getVersion() == $policyVersion ) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: [{}|{}|{}]", drools.getRule().getName(), + $params.getPolicyScope(), $params.getPolicyName(), $params.getPolicyVersion()); + + retract($params); +end + +/* +* +* This rule responds to DCAE Events where there is no manager yet. Either it is +* the first ONSET, or a subsequent badly formed Event (i.e. Syntax error, or is-closed-loop-disabled) +* +*/ +rule "EVENT" + when + $params : ControlLoopParams( $clName : getClosedLoopControlName() ) + $event : CanonicalOnset( closedLoopControlName == $clName ) + not ( UsecasesEventManager( closedLoopControlName == $event.getClosedLoopControlName(), + getEvent() == $event ) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: event={}", + $clName, $params.getPolicyName(), drools.getRule().getName(), + $event); + // + // Retract the event from memory; it will be managed by the manager from now on + // + retract($event); + + VirtualControlLoopNotification notification = null; + + try { + // + // Check the event, because we need it to not be null when + // we create the UsecasesEventManager. The UsecasesEventManager + // will do extra syntax checking as well as check if the closed loop is disabled. + // + if ($event.getRequestId() == null) { + notification = new VirtualControlLoopNotification($event); + notification.setNotification(ControlLoopNotificationType.REJECTED); + notification.setFrom("policy"); + notification.setMessage("Missing requestId"); + notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName()); + notification.setPolicyVersion($params.getPolicyVersion()); + + } else { + UsecasesEventManager manager = new UsecasesEventManager($params, $event, drools.getWorkingMemory()); + insert(manager); + try { + // load the first policy/step + manager.start(); + + if (manager.getSteps().isEmpty()) { + // no steps implies no policies, thus go straight to DONE state + manager.setState(State.DONE); + + manager.setAccepted(true); + + notification = manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.ACTIVE); + notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName()); + + } else { + // Note: the notification will be generated lazily + manager.setState(State.POLICY_LOADED); + } + + } catch(Exception e) { + retract(manager); + throw e; + } + } + } catch (Exception e) { + logger.warn("{}: {}.{}: error starting manager", $clName, $params.getPolicyName(), + drools.getRule().getName(), e); + notification = new VirtualControlLoopNotification($event); + notification.setNotification(ControlLoopNotificationType.REJECTED); + notification.setMessage("Exception occurred: " + e.getMessage()); + notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName()); + notification.setPolicyVersion($params.getPolicyVersion()); + } + // + // Generate notification + // + try { + if (notification != null) { + PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification); + } + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: event={} exception generating notification", + $clName, $params.getPolicyName(), drools.getRule().getName(), + $event, e); + } +end + +/* +* +* This rule fires when we get a subsequent event. +* +*/ +rule "EVENT.MANAGER.NEW.EVENT" + when + $event : VirtualControlLoopEvent( ) + $manager : UsecasesEventManager( closedLoopControlName == $event.getClosedLoopControlName(), + getEvent() == $event ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: event={} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $event, $manager); + // + // Remove the event from memory + // + retract($event); + + // + // Check what kind of event this is + // + switch($manager.onNewEvent($event)) { + case SYNTAX_ERROR: + // + // Ignore any bad syntax events + // + logger.warn("{}: {}.{}: syntax error", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName()); + break; + + case FIRST_ABATEMENT: + case SUBSEQUENT_ABATEMENT: + // + // TODO: handle the abatement. Currently, it's just discarded. + // + logger.info("{}: {}.{}: abatement", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName()); + break; + + case FIRST_ONSET: + case SUBSEQUENT_ONSET: + default: + // + // We don't care about subsequent onsets + // + logger.warn("{}: {}.{}: subsequent onset", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName()); + break; + } +end + +/* +* +* All steps have been executed, load the next policy. +* +*/ +rule "EVENT.MANAGER.LOAD.NEXT.POLICY" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.POLICY_LOADED, + getSteps().isEmpty() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager); + + try { + $manager.loadNextPolicy($manager.getResult()); + + if ($manager.getSteps().isEmpty()) { + // no steps - must be the final policy + $manager.setState(State.DONE); + } + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception loading next policy", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to load next policy"); + } + + update($manager); +end + +/* +* +* Policy loaded, identify any preprocessor steps that need to be run first. +* +*/ +rule "EVENT.MANAGER.PREPROCESS" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.POLICY_LOADED, + $step : getSteps().peek(), + $step != null, + !$step.isPreprocessed() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + /* + * Load any preprocessor steps. + * + * Note: this will not change the state of the manager, but it may change the + * state of the step. + */ + $step.setPreprocessed(true); + $manager.loadPreprocessorSteps(); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception loading preprocessor steps", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to load preprocessing steps"); + } + + update($manager); +end + +/* +* +* Accepts the event, when ready to execute a step of interest. Does not change the +* state of the manager, leaving that to be done by rule "EVENT.MANAGER.EXECUTE.STEP". +* +*/ +rule "EVENT.MANAGER.ACCEPT" + salience 200 + when + $manager : UsecasesEventManager( + isActive(), + !isAccepted(), + getState() == State.POLICY_LOADED, + $step : getSteps().peek(), + $step != null, + $step.isPreprocessed(), + $step.acceptsEvent() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $manager.setAccepted(true); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.ACTIVE); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to accept the event"); + } + + update($manager); +end + +/* +* +* Ready to execute the step. +* +*/ +rule "EVENT.MANAGER.EXECUTE.STEP" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.POLICY_LOADED, + $step : getSteps().peek(), + $step != null, + $step.isPreprocessed() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $step.init(); + $step.setProperties(); + + if ($manager.executeStep()) { + $manager.setState(State.AWAITING_OUTCOME); + + } else { + // this step is no longer necessary - try the next one + $manager.nextStep(); + } + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception executing a step", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to execute the next step"); + } + + update($manager); +end + +/* +* +* Generate SDNR notification. Does not discard the outcome from the queue, leaving it to be +* handled by rule "EVENT.MANAGER.PROCESS.OUTCOME". +* +*/ +rule "EVENT.MANAGER.GENERATE.SDNR.NOTIFICATION" + // this should fire BEFORE the "EVENT.MANAGER.PROCESS.OUTCOME" rule + salience 100 + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + $outcome.getEnd() != null, + !isAbort($outcome), + $step : getSteps().peek(), + "SDNR".equals($step.getActorName()), + $outcome.isFor("SDNR", $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome); + $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception generating SDNR Response notification", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + } +end + +/* +* +* Process a GUARD outcome. Does not discard the outcome from the queue, leaving it to be +* handled by rule "EVENT.MANAGER.PROCESS.OUTCOME". +* +*/ +rule "EVENT.MANAGER.PROCESS.GUARD.OUTCOME" + salience 100 + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + !isAbort($outcome), + $step : getSteps().peek(), + "GUARD".equals($step.getActorName()), + $outcome.isFor("GUARD", $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.OPERATION); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory(Collections.emptyList()); + + // get actor/operation name from the policy step, not from the guard step + Step step2 = $step.getParentStep(); + + if ($outcome.getEnd() == null) { + // it's a "start" operation + notification.setMessage("Sending guard query for " + step2.getActorName() + " " + step2.getOperationName()); + + } else if ($outcome.getResult() == PolicyResult.SUCCESS) { + notification.setMessage("Guard result for " + step2.getActorName() + " " + step2.getOperationName() + + " is Permit"); + } else { + // it's a failure + notification.setMessage("Guard result for " + step2.getActorName() + " " + step2.getOperationName() + + " is Deny"); + } + + $manager.deliver("POLICY-CL-MGT", notification, "GUARD notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception generating GUARD notification", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + } +end + +/* +* +* Process an outcome when the policy's operation starts. +* +*/ +rule "EVENT.MANAGER.PROCESS.POLICY.STARTED" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + $outcome.getEnd() == null, + $step : getSteps().peek(), + $step.isPolicyStep(), + $outcome.isFor($step.getActorName(), $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $manager.getOutcomes().remove(); + + // it's a "start" operation for the step + $manager.bumpAttempts(); + + $manager.addToHistory($outcome); + $manager.storeInDataBase($manager.getPartialHistory().peekLast()); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.OPERATION); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory(Collections.emptyList()); + notification.setMessage($manager.getOperationMessage()); + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'start' outcome"); + } + + update($manager); +end + +/* +* +* Process an outcome when an arbitrary Preprocessor step starts. +* +*/ +rule "EVENT.MANAGER.PROCESS.PREPROCESSOR.STARTED" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + $outcome.getEnd() == null, + $step : getSteps().peek(), + !$step.isPolicyStep(), + $outcome.isFor($step.getActorName(), $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $manager.getOutcomes().remove(); + + // it's a "start" operation for the step + $manager.bumpAttempts(); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle 'start' outcome"); + } + + update($manager); +end + +/* +* +* Process an outcome when the policy's operation succeeds. +* +*/ +rule "EVENT.MANAGER.PROCESS.POLICY.SUCCESS" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + $outcome.getEnd() != null, + $outcome.getResult() == PolicyResult.SUCCESS, + $step : getSteps().peek(), + $step.isPolicyStep(), + $outcome.isFor($step.getActorName(), $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $manager.getOutcomes().remove(); + + // let the step record the response that's contained within the outcome + $step.success($outcome); + + $manager.addToHistory($outcome); + $manager.storeInDataBase($manager.getPartialHistory().peekLast()); + + $manager.setResult($outcome.getResult()); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation) + .collect(Collectors.toList())); + + // this step is complete - discard it + $manager.getSteps().remove(); + + $manager.setState(State.POLICY_LOADED); + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'success' outcome"); + } + + update($manager); +end + +/* +* +* Process a final failure outcome, when the event has been accepted. +* +*/ +rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.ACCEPTED" + when + $manager : UsecasesEventManager( + isActive(), + isAccepted(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + !isAbort($outcome), + $outcome.getEnd() != null, + $outcome.isFinalOutcome(), + $outcome.getResult() != PolicyResult.SUCCESS, + $step : getSteps().peek() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + $manager.getOutcomes().remove(); + + if (!$outcome.isFor($step.getActorName(), $step.getOperationName())) { + $outcome.setResult(PolicyResult.FAILURE_GUARD); + $outcome.setMessage("Operation denied by " + $outcome.getActor()); + } + + // final failure for this policy + $manager.addToHistory($outcome); + $manager.storeInDataBase($manager.getPartialHistory().peekLast()); + + $manager.setResult($outcome.getResult()); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation) + .collect(Collectors.toList())); + + // trigger move to the next policy - clear all steps + $manager.getSteps().clear(); + $manager.setState(State.POLICY_LOADED); + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'failure' outcome"); + } + + update($manager); +end + +/* +* +* Process a final failure outcome, when the event has NOT been accepted. This typically +* occurs when an A&AI query fails BEFORE the first lock has been requested (and thus +* before the first policy's operation has been started). +* +*/ +rule "EVENT.MANAGER.PROCESS.FINAL.FAILURE.REJECTED" + when + $manager : UsecasesEventManager( + isActive(), + !isAccepted(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + !isAbort($outcome), + $outcome.getEnd() != null, + $outcome.isFinalOutcome(), + $outcome.getResult() != PolicyResult.SUCCESS, + $step : getSteps().peek() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + retract($manager); + + try { + // final failure for this policy + $manager.addToHistory($outcome); + + $manager.setResult($outcome.getResult()); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.REJECTED); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory($manager.getPartialHistory().stream().map(OperationOutcome2::getClOperation) + .collect(Collectors.toList())); + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to reject event"); + } + + $manager.destroy(); +end + +/* +* +* Process an outcome when the policy's operation fails. +* +*/ +rule "EVENT.MANAGER.PROCESS.POLICY.FAILURE" + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + !isAbort($outcome), + $outcome.getEnd() != null, + !$outcome.isFinalOutcome(), + $outcome.getResult() != PolicyResult.SUCCESS, + $step : getSteps().peek(), + $step.isPolicyStep(), + $outcome.isFor($step.getActorName(), $step.getOperationName()) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + // not a final failure, thus it will be retried automatically + + $manager.getOutcomes().remove(); + + // do NOT invoke manager.setResult() + + $manager.addToHistory($outcome); + $manager.storeInDataBase($manager.getPartialHistory().peekLast()); + + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle policy 'failure' outcome"); + } + + update($manager); +end + +/* +* +* Discard an outcome that was not handled by any other rule. +* +*/ +rule "EVENT.MANAGER.DISCARD.OUTCOME" + salience -10 + when + $manager : UsecasesEventManager( + isActive(), + getState() == State.AWAITING_OUTCOME, + $outcome : getOutcomes().peek(), + $outcome != null, + $step : getSteps().peek() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $outcome.getResult(), $manager); + + try { + $manager.getOutcomes().remove(); + + if ($outcome.getEnd() != null && $outcome.isFor($step.getActorName(), $step.getOperationName())) { + // it's a completion for the step + + // let the step record the response that's contained within the outcome + if ($outcome.getResult() == PolicyResult.SUCCESS) { + $step.success($outcome); + } + + // this step is complete - discard it + $manager.getSteps().remove(); + + $manager.setState(State.POLICY_LOADED); + } + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception processing operation outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle outcome"); + } + + update($manager); +end + +/* +* +* Abort processing. This can happen in any state (once the manager has been started). +* +*/ +rule "EVENT.MANAGER.ABORT" + when + $manager : UsecasesEventManager( + isActive(), + getState() != State.DONE, + $outcome : getOutcomes().peek(), + $outcome != null, + isAbort($outcome), + $step : getSteps().peek() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: {} manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $step, $manager); + + try { + // determine the final message + String msg; + switch ($outcome.getActor()) { + case ActorConstants.CL_TIMEOUT_ACTOR: + msg = "Control Loop timed out"; + break; + case ActorConstants.LOCK_ACTOR: + msg = "Target Lock was lost"; + break; + default: + msg = "Processing aborted by " + $outcome.getActor(); + break; + } + + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE, msg); + + if ($step != null && "SDNR".equals($step.getActorName()) + && $outcome.isFor($step.getActorName(), $step.getOperationName())) { + + // aborted while processing the SDNR step - generate a notification + ControlLoopResponse clResponse = $manager.makeControlLoopResponse($outcome); + $manager.deliver("DCAE_CL_RSP", clResponse, "SDNR notification", drools.getRule().getName()); + } + + if ($step != null) { + $outcome.setActor($step.getActorName()); + $outcome.setOperation($step.getOperationName()); + + $manager.addToHistory($outcome); + $manager.storeInDataBase($manager.getPartialHistory().peekLast()); + } + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception handling ABORT outcome", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + $manager.abort(State.DONE, FinalResult.FINAL_FAILURE_EXCEPTION, "failed to handle ABORT"); + } + + update($manager); +end + +/* +* +* Done processing. Arriving here implies that the event has been accepted. +* +*/ +rule "EVENT.MANAGER.FINAL" + when + $manager : UsecasesEventManager( + !isActive() || getState() == State.DONE ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}.{}: manager={}", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager); + + retract($manager); + + try { + VirtualControlLoopNotification notification = $manager.makeNotification(); + notification.setPolicyName($manager.getPolicyName() + "." + drools.getRule().getName()); + notification.setHistory($manager.getFullHistory().stream().map(OperationOutcome2::getClOperation) + .collect(Collectors.toList())); + + FinalResult finalResult = $manager.getFinalResult(); + if (finalResult == null) { + finalResult = ($manager.isActive() ? FinalResult.FINAL_SUCCESS : FinalResult.FINAL_FAILURE); + } + + switch (finalResult) { + case FINAL_FAILURE_EXCEPTION: + notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE); + notification.setMessage("Exception in processing closed loop"); + break; + case FINAL_SUCCESS: + notification.setNotification(ControlLoopNotificationType.FINAL_SUCCESS); + break; + case FINAL_OPENLOOP: + notification.setNotification(ControlLoopNotificationType.FINAL_OPENLOOP); + break; + case FINAL_FAILURE: + default: + notification.setNotification(ControlLoopNotificationType.FINAL_FAILURE); + break; + } + + if ($manager.getFinalMessage() != null) { + notification.setMessage($manager.getFinalMessage()); + } + + $manager.deliver("POLICY-CL-MGT", notification, "notification", drools.getRule().getName()); + + } catch(RuntimeException e) { + logger.warn("{}: {}.{}: manager={} exception generating final notification", + $manager.getClosedLoopControlName(), $manager.getPolicyName(), drools.getRule().getName(), + $manager, e); + } + + $manager.destroy(); +end + +/* +* +* This rule will clean up any rogue events where there is no +* ControlLoopParams object corresponding to the onset event. +* +*/ +rule "EVENT.CLEANUP" + salience -100 + when + $event : VirtualControlLoopEvent( $clName: closedLoopControlName ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}", $clName, drools.getRule().getName()); + logger.debug("{}: {}: orphan event={}", + $clName, drools.getRule().getName(), $event); + // + // Retract the event + // + retract($event); +end + +/* +* +* At this point, it appears that if we prevent the rules from getting messages from +* topics, then that will also prevent the actors from getting them. So the following +* rules are here just to discard those messages. +* +* These have a higher salience so the objects are removed before the "FINAL" message +* is processed, so that the junit test can assume things are done once they see the +* "FINAL" message. Otherwise, tests might fail sporadically. +* +*/ +rule "APPC.Response.CLEANUP" + salience 1 + when + $msg : org.onap.policy.appc.Response( ) + then + retract($msg); +end + +rule "APPC.Request.CLEANUP" + salience 1 + when + $msg : org.onap.policy.appc.Request( ) + then + retract($msg); +end + +rule "APPC-LCM.Response.CLEANUP" + salience 1 + when + $msg : org.onap.policy.appclcm.AppcLcmDmaapWrapper( ) + then + retract($msg); +end + +rule "SDNR.Response.CLEANUP" + salience 1 + when + $msg : org.onap.policy.sdnr.PciResponseWrapper( ) + then + retract($msg); +end diff --git a/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java new file mode 100644 index 000000000..b9864bdd7 --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/java/org/onap/policy/controlloop/UsecasesTest.java @@ -0,0 +1,119 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.controlloop; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.onap.policy.controlloop.common.rules.test.DroolsRuleTest; +import org.onap.policy.controlloop.common.rules.test.Listener; +import org.onap.policy.controlloop.common.rules.test.NamedRunner; +import org.onap.policy.controlloop.common.rules.test.TestNames; +import org.onap.policy.drools.apps.controller.usecases.UsecasesEventManager; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.simulators.Util; + +/** + * Tests use cases using Usecases rules. + * + *

+ * Note: this runs ALL tests (i.e., any whose names start with "test"). + */ +@RunWith(NamedRunner.class) +@TestNames(prefixes = {"test"}) + +public class UsecasesTest extends DroolsRuleTest { + protected static final String CONTROLLER_NAME = "usecases"; + + + /** + * Sets up statics. + */ + @BeforeClass + public static void setUpBeforeClass() { + initStatics(CONTROLLER_NAME); + + rules.configure("src/main/resources"); + rules.start(); + httpClients.addClients("usecases"); + simulators.start(Util::buildAaiSim, Util::buildSoSim, Util::buildVfcSim, Util::buildGuardSim, + Util::buildSdncSim); + } + + /** + * Cleans up statics. + */ + @AfterClass + public static void tearDownAfterClass() { + finishStatics(); + } + + /** + * Sets up. + */ + @Before + public void setUp() { + init(); + } + + /** + * Tears down. + */ + @After + public void tearDown() { + finish(); + } + + @Override + protected void waitForLockAndPermit(ToscaPolicy policy, Listener policyClMgt) { + String policyName = policy.getIdentifier().getName(); + + policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.ACTIVE + && (policyName + ".EVENT.MANAGER.ACCEPT").equals(notif.getPolicyName())); + + policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION + && (policyName + ".EVENT.MANAGER.PROCESS.GUARD.OUTCOME").equals(notif.getPolicyName()) + && notif.getMessage().startsWith("Sending guard query")); + + policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION + && (policyName + ".EVENT.MANAGER.PROCESS.GUARD.OUTCOME").equals(notif.getPolicyName()) + && notif.getMessage().startsWith("Guard result") && notif.getMessage().endsWith("Permit")); + + policyClMgt.await(notif -> notif.getNotification() == ControlLoopNotificationType.OPERATION + && (policyName + ".EVENT.MANAGER.PROCESS.POLICY.STARTED").equals(notif.getPolicyName()) + && notif.getMessage().startsWith("actor=")); + } + + @Override + protected VirtualControlLoopNotification waitForFinal(ToscaPolicy policy, + Listener policyClMgt, ControlLoopNotificationType finalType) { + + return policyClMgt.await(notif -> notif.getNotification() == finalType + && (policy.getIdentifier().getName() + ".EVENT.MANAGER.FINAL").equals(notif.getPolicyName())); + } + + @Override + protected long getCreateCount() { + return UsecasesEventManager.getCreateCount(); + } +} diff --git a/controlloop/common/controller-usecases/src/test/resources/usecases.pom b/controlloop/common/controller-usecases/src/test/resources/usecases.pom new file mode 100644 index 000000000..e30417ef0 --- /dev/null +++ b/controlloop/common/controller-usecases/src/test/resources/usecases.pom @@ -0,0 +1,30 @@ + + + + + + 4.0.0 + + org.onap.policy.controlloop + usecases + 1.1.0 + diff --git a/controlloop/common/feature-controlloop-usecases/pom.xml b/controlloop/common/feature-controlloop-usecases/pom.xml new file mode 100644 index 000000000..1f8ac2f4b --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + + org.onap.policy.drools-applications.controlloop.common + drools-applications-common + 1.7.1-SNAPSHOT + + + feature-controlloop-usecases + + + Load Experimental Usecases Control Loop Use Cases Controller as a feature. + + + + + + src/main/feature + true + + + src/main/resources + + + + + maven-assembly-plugin + + + zipfile + + single + + package + + true + ${project.artifactId}-${project.version} + + src/assembly/assemble_zip.xml + + false + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + + copy-dependencies + + prepare-package + + ${project.build.directory}/assembly/lib + false + true + true + false + false + false + runtime + true + + + + + + + + + + org.onap.policy.drools-applications.controlloop.common + controller-usecases + ${project.version} + + + org.onap.policy.drools-pdp + policy-management + ${version.policy.drools-pdp} + provided + + + junit + junit + test + + + diff --git a/controlloop/common/feature-controlloop-usecases/src/assembly/assemble_zip.xml b/controlloop/common/feature-controlloop-usecases/src/assembly/assemble_zip.xml new file mode 100644 index 000000000..860ab2a23 --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/assembly/assemble_zip.xml @@ -0,0 +1,85 @@ + + + + + + feature-controlloop-usecases-package + + zip + + + false + + + + target + lib/feature + + feature-controlloop-usecases-${project.version}.jar + + + + target/assembly/lib + artifacts + + controller-usecases-${project.version}.jar + + + + target/assembly/lib + lib/dependencies + + *.jar + + + controller-usecases-${project.version}.jar + + + + target/classes/config + config + 0644 + + + + src/main/feature/bin + bin + 0755 + + + + src/main/feature/db + db + 0744 + + + + src/main/feature/install + install + 0755 + + + + + diff --git a/controlloop/common/feature-controlloop-usecases/src/main/feature/config/logback-include-usecases.xml b/controlloop/common/feature-controlloop-usecases/src/main/feature/config/logback-include-usecases.xml new file mode 100644 index 000000000..655ccd7ca --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/main/feature/config/logback-include-usecases.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + ${logDir}/${usecasesLog}.log + + ${logDir}/${usecasesLog}.%d{yyyy-MM-dd}.%i.log.zip + 50MB + 30 + 10GB + + + ${networkPattern} + + + + + + + + + + + + diff --git a/controlloop/common/feature-controlloop-usecases/src/main/feature/config/usecases-controller.properties b/controlloop/common/feature-controlloop-usecases/src/main/feature/config/usecases-controller.properties new file mode 100644 index 000000000..73c41123f --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/main/feature/config/usecases-controller.properties @@ -0,0 +1,64 @@ +### +# ============LICENSE_START======================================================= +# ONAP +# ================================================================================ +# Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. +# ================================================================================ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END========================================================= +### + +controller.name=usecases + +dmaap.source.topics=DCAE_TOPIC,APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP +dmaap.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL,DCAE_CL_RSP + +dmaap.source.topics.DCAE_TOPIC.events=\ + org.onap.policy.controlloop.CanonicalOnset,org.onap.policy.controlloop.CanonicalAbated +dmaap.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalOnset.\ + filter=[?($.closedLoopEventStatus == 'ONSET')] +dmaap.source.topics.DCAE_TOPIC.events.org.onap.policy.controlloop.CanonicalAbated.\ + filter=[?($.closedLoopEventStatus == 'ABATED')] +dmaap.source.topics.DCAE_TOPIC.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gson + +dmaap.source.topics.APPC-CL.events=org.onap.policy.appc.Response +dmaap.source.topics.APPC-CL.events.org.onap.policy.appc.Response.filter=[?($.CommonHeader && $.Status)] +dmaap.source.topics.APPC-CL.events.custom.gson=org.onap.policy.appc.util.Serialization,gsonPretty + +dmaap.source.topics.APPC-LCM-WRITE.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper +dmaap.source.topics.APPC-LCM-WRITE.events.org.onap.policy.appclcm.AppcLcmDmaapWrapper.filter=[?($.type == 'response')] +dmaap.source.topics.APPC-LCM-WRITE.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson + +dmaap.sink.topics.APPC-CL.events=org.onap.policy.appc.Request +dmaap.sink.topics.APPC-CL.events.custom.gson=org.onap.policy.appc.util.Serialization,gsonPretty + +dmaap.sink.topics.APPC-LCM-READ.events=org.onap.policy.appclcm.AppcLcmDmaapWrapper +dmaap.sink.topics.APPC-LCM-READ.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson + +dmaap.sink.topics.POLICY-CL-MGT.events=org.onap.policy.controlloop.VirtualControlLoopNotification +dmaap.sink.topics.POLICY-CL-MGT.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty + +dmaap.sink.topics.SDNR-CL.events=org.onap.policy.sdnr.PciRequestWrapper +dmaap.sink.topics.SDNR-CL.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson + +dmaap.sink.topics.DCAE_CL_RSP.events=org.onap.policy.controlloop.ControlLoopResponse +dmaap.sink.topics.DCAE_CL_RSP.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty + +dmaap.source.topics.SDNR-CL-RSP.events=org.onap.policy.sdnr.PciResponseWrapper +dmaap.source.topics.SDNR-CL-RSP.events.org.onap.policy.sdnr.PciResponseWrapper.filter=[?($.type == 'response')] +dmaap.source.topics.SDNR-CL-RSP.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson + +rules.groupId=${project.groupId} +rules.artifactId=controller-usecases +rules.version=${project.version} + diff --git a/controlloop/common/feature-controlloop-usecases/src/main/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeature.java b/controlloop/common/feature-controlloop-usecases/src/main/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeature.java new file mode 100644 index 000000000..1f8e2545e --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/main/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeature.java @@ -0,0 +1,43 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.apps.controlloop.feature.usecases; + +import org.onap.policy.drools.features.PolicyEngineFeatureApi; + +/** + * Usecases installation as a feature saves time + * loading the Usecases controller at runtime over the + * usual installation from nexus. + * + *

This class will be expanded in the future for additional + * functionality + * + */ +public class UsecasesFeature implements PolicyEngineFeatureApi { + + public static final int SEQNO = 1000; + + @Override + public int getSequenceNumber() { + return SEQNO; + } + +} diff --git a/controlloop/common/feature-controlloop-usecases/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi b/controlloop/common/feature-controlloop-usecases/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi new file mode 100644 index 000000000..3a8263942 --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi @@ -0,0 +1 @@ +org.onap.policy.drools.apps.controlloop.feature.usecases.UsecasesFeature diff --git a/controlloop/common/feature-controlloop-usecases/src/test/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeatureTest.java b/controlloop/common/feature-controlloop-usecases/src/test/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeatureTest.java new file mode 100644 index 000000000..ed1bba23d --- /dev/null +++ b/controlloop/common/feature-controlloop-usecases/src/test/java/org/onap/policy/drools/apps/controlloop/feature/usecases/UsecasesFeatureTest.java @@ -0,0 +1,31 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.apps.controlloop.feature.usecases; + +import static org.junit.Assert.assertEquals; + +public class UsecasesFeatureTest { + + @org.junit.Test + public void getSequenceNumber() { + assertEquals(UsecasesFeature.SEQNO, new UsecasesFeature().getSequenceNumber()); + } +} diff --git a/controlloop/common/pom.xml b/controlloop/common/pom.xml index 7298db6c2..4ab1b490e 100644 --- a/controlloop/common/pom.xml +++ b/controlloop/common/pom.xml @@ -42,6 +42,7 @@ feature-controlloop-trans feature-controlloop-management feature-controlloop-frankfurt + feature-controlloop-usecases diff --git a/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml b/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml index cc0009735..9ace783c0 100644 --- a/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml +++ b/controlloop/common/rules-test/src/test/resources/META-INF/kmodule.xml @@ -20,7 +20,7 @@ --> + packages="org.onap.policy.controlloop"> diff --git a/controlloop/packages/docker-controlloop/src/main/docker/Dockerfile b/controlloop/packages/docker-controlloop/src/main/docker/Dockerfile index 3e60c9597..efb54b6e4 100644 --- a/controlloop/packages/docker-controlloop/src/main/docker/Dockerfile +++ b/controlloop/packages/docker-controlloop/src/main/docker/Dockerfile @@ -13,13 +13,17 @@ RUN unzip apps-controlloop.zip && \ . $POLICY_HOME/etc/profile.d/env.sh && \ $POLICY_HOME/bin/features install controlloop-utils controlloop-trans controlloop-management && \ $POLICY_HOME/bin/features install controlloop-frankfurt && \ + $POLICY_HOME/bin/features install controlloop-usecases && \ $POLICY_HOME/bin/features enable healthcheck distributed-locking lifecycle && \ $POLICY_HOME/bin/features enable controlloop-trans controlloop-management && \ $POLICY_HOME/bin/features enable controlloop-frankfurt && \ + $POLICY_HOME/bin/features enable controlloop-usecases && \ $POLICY_HOME/bin/deploy-artifact -l -d -s $POLICY_HOME/etc/m2/standalone-settings.xml \ -a $POLICY_HOME/features/controlloop-management/lib/feature/feature-controlloop-management-$BUILD_VERSION_APP_CL.jar && \ $POLICY_HOME/bin/deploy-artifact -l -d -s $POLICY_HOME/etc/m2/standalone-settings.xml \ -a $POLICY_HOME/features/controlloop-frankfurt/artifacts/controller-frankfurt-$BUILD_VERSION_APP_CL.jar && \ + $POLICY_HOME/bin/deploy-artifact -l -d -s $POLICY_HOME/etc/m2/standalone-settings.xml \ + -a $POLICY_HOME/features/controlloop-usecases/artifacts/controller-usecases-$BUILD_VERSION_APP_CL.jar && \ find $HOME/.m2/ -name _maven.repositories -exec rm -v {} \; && \ find $HOME/.m2/ -name _remote.repositories -exec rm -v {} \; && \ rm $POLICY_INSTALL/apps-controlloop.zip $POLICY_INSTALL/basex-controlloop-$BUILD_VERSION_APP_CL.tar.gz 2> /dev/null -- cgit 1.2.3-korg