From 882933502c0eedc219197fa8c39a2cb733ea6729 Mon Sep 17 00:00:00 2001 From: Saravanan A Date: Tue, 9 Oct 2018 16:20:52 +0530 Subject: Add implementation for OOF PCI use case Receive DMaaP message from PCI-Handler MS with PCI Config change recommendations through DCAE_CL_OUTPUT topic. Trigger SDN-R (if allowed by policy) by sending DMaaP request through SDNR-CL topic. When the response is received from SDNR through SDNR-CL-RSP topic, just parse and print. Code review comments addressed Added controller changes into amsterdam too. Change-Id: I93e54d3f44b4266092931a5f05b766cc26f2a869 Issue-ID: POLICY-1089 Signed-off-by: Saravanan A --- .../common/feature-controlloop-amsterdam/pom.xml | 16 + .../feature/config/amsterdam-controller.properties | 20 +- .../controlloop/policy/ControlLoopPolicyTest.java | 5 + .../resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml | 39 ++ .../config/__artifactId__-controller.properties | 19 +- .../config/__artifactId__-controller.rest.json | 14 +- .../src/main/config/vPCI.pcims.onset.json | 18 + .../src/main/config/vPCI.sdnr.success.json | 23 ++ .../archetype-resources/src/main/config/vPCI.yaml | 38 ++ .../main/resources/__closedLoopControlName__.drl | 118 ++++++ .../policy/template/demo/VpciControlLoopTest.java | 420 +++++++++++++++++++++ .../resources/yaml/policy_ControlLoop_vPCI.yaml | 38 ++ 12 files changed, 762 insertions(+), 6 deletions(-) create mode 100644 controlloop/common/policy-yaml/src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml create mode 100644 controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.pcims.onset.json create mode 100644 controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.sdnr.success.json create mode 100644 controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.yaml create mode 100644 controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VpciControlLoopTest.java create mode 100644 controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vPCI.yaml diff --git a/controlloop/common/feature-controlloop-amsterdam/pom.xml b/controlloop/common/feature-controlloop-amsterdam/pom.xml index 15f0c35b2..273d05652 100644 --- a/controlloop/common/feature-controlloop-amsterdam/pom.xml +++ b/controlloop/common/feature-controlloop-amsterdam/pom.xml @@ -105,6 +105,11 @@ appclcm ${project.version} + + org.onap.policy.drools-applications.controlloop.common.model-impl + sdnr + ${project.version} + org.onap.policy.drools-applications.controlloop.common.model-impl vfc @@ -173,6 +178,17 @@ + + org.onap.policy.drools-applications.controlloop.common.actors + actor.sdnr + ${project.version} + + + guava + com.google.guava + + + org.onap.policy.drools-applications.controlloop.common.actors actor.so diff --git a/controlloop/common/feature-controlloop-amsterdam/src/main/feature/config/amsterdam-controller.properties b/controlloop/common/feature-controlloop-amsterdam/src/main/feature/config/amsterdam-controller.properties index 0d5013868..d7dc0c1c0 100644 --- a/controlloop/common/feature-controlloop-amsterdam/src/main/feature/config/amsterdam-controller.properties +++ b/controlloop/common/feature-controlloop-amsterdam/src/main/feature/config/amsterdam-controller.properties @@ -20,7 +20,7 @@ controller.name=amsterdam -dmaap.source.topics=${{DCAE_TOPIC}},APPC-CL,APPC-LCM-WRITE +dmaap.source.topics=${{DCAE_TOPIC}},APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP dmaap.source.topics.${{DCAE_TOPIC}}.servers=${{DCAE_SERVERS}} dmaap.source.topics.${{DCAE_TOPIC}}.apiKey= @@ -47,7 +47,15 @@ dmaap.source.topics.APPC-LCM-WRITE.events.org.onap.policy.appclcm.LcmResponseWra dmaap.source.topics.APPC-LCM-WRITE.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson dmaap.source.topics.APPC-LCM-WRITE.https=true -dmaap.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT +dmaap.source.topics.SDNR-CL-RSP.servers=${{DMAAP_SERVERS}} +dmaap.source.topics.SDNR-CL-RSP.apiKey= +dmaap.source.topics.SDNR-CL-RSP.apiSecret= +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 +dmaap.source.topics.SDNR-CL-RSP.https=true + +dmaap.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL dmaap.sink.topics.APPC-CL.servers=${{DMAAP_SERVERS}} dmaap.sink.topics.APPC-CL.apiKey= @@ -70,6 +78,14 @@ dmaap.sink.topics.POLICY-CL-MGT.events=org.onap.policy.controlloop.VirtualContro dmaap.sink.topics.POLICY-CL-MGT.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty dmaap.sink.topics.POLICY-CL-MGT.https=true +dmaap.sink.topics.SDNR-CL.servers=${{DMAAP_SERVERS}} +dmaap.sink.topics.SDNR-CL.apiKey= +dmaap.sink.topics.SDNR-CL.apiSecret= +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.SDNR-CL.https=true + rules.groupId= rules.artifactId= rules.version= + diff --git a/controlloop/common/policy-yaml/src/test/java/org/onap/policy/controlloop/policy/ControlLoopPolicyTest.java b/controlloop/common/policy-yaml/src/test/java/org/onap/policy/controlloop/policy/ControlLoopPolicyTest.java index a4d1baa75..00c70052e 100644 --- a/controlloop/common/policy-yaml/src/test/java/org/onap/policy/controlloop/policy/ControlLoopPolicyTest.java +++ b/controlloop/common/policy-yaml/src/test/java/org/onap/policy/controlloop/policy/ControlLoopPolicyTest.java @@ -74,6 +74,11 @@ public class ControlLoopPolicyTest { this.test("src/test/resources/v2.0.0/policy_ONAP_UseCase_vCPE.yaml"); } + @Test + public void testvpci() { + this.test("src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml"); + } + @Test public void testvolte() { this.test("src/test/resources/v2.0.0/policy_ONAP_UseCase_VOLTE.yaml"); diff --git a/controlloop/common/policy-yaml/src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml b/controlloop/common/policy-yaml/src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml new file mode 100644 index 000000000..3d47b643a --- /dev/null +++ b/controlloop/common/policy-yaml/src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml @@ -0,0 +1,39 @@ +# Copyright 2018 Wipro Limited 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. +controlLoop: + version: 3.0.0 + controlLoopName: ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459 + trigger_policy: unique-policy-id-123-modifyconfig + timeout: 1200 + abatement: false + +policies: + - id: unique-policy-id-123-modifyconfig + name: modify PCI config + description: + actor: SDNR + recipe: ModifyConfig + target: + # These fields are not used + resourceID: Eace933104d443b496b8.nodes.heat.vpg + type: VNF + retry: 0 + timeout: 300 + success: final_success + failure: final_failure + failure_timeout: final_failure_timeout + failure_retries: final_failure_retries + failure_exception: final_failure_exception + failure_guard: final_failure_guard + diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.properties b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.properties index 6b59b719f..3e67dca51 100644 --- a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.properties +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.properties @@ -20,7 +20,7 @@ controller.name=${artifactId} -dmaap.source.topics=${dcaeTopic},APPC-CL,APPC-LCM-WRITE +dmaap.source.topics=${dcaeTopic},APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP dmaap.source.topics.${dcaeTopic}.servers=${dcaeServers} dmaap.source.topics.${dcaeTopic}.apiKey= @@ -46,7 +46,15 @@ dmaap.source.topics.APPC-LCM-WRITE.events.org.onap.policy.appclcm.LcmResponseWra dmaap.source.topics.APPC-LCM-WRITE.events.custom.gson=org.onap.policy.appclcm.util.Serialization,gson dmaap.source.topics.APPC-LCM-WRITE.https=true -noop.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT +dmaap.source.topics.SDNR-CL-RSP.servers=${dmaapServers} +dmaap.source.topics.SDNR-CL-RSP.apiKey= +dmaap.source.topics.SDNR-CL-RSP.apiSecret= +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 +dmaap.source.topics.SDNR-CL-RSP.https=true + +noop.sink.topics=APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL noop.sink.topics.APPC-CL.servers=${dmaapServers} noop.sink.topics.APPC-CL.apiKey= @@ -66,6 +74,13 @@ noop.sink.topics.POLICY-CL-MGT.apiSecret= noop.sink.topics.POLICY-CL-MGT.events=org.onap.policy.controlloop.VirtualControlLoopNotification noop.sink.topics.POLICY-CL-MGT.events.custom.gson=org.onap.policy.controlloop.util.Serialization,gsonPretty +noop.sink.topics.SDNR-CL.servers=${dmaapServers} +noop.sink.topics.SDNR-CL.apiKey= +noop.sink.topics.SDNR-CL.apiSecret= +noop.sink.topics.SDNR-CL.events=org.onap.policy.sdnr.PciRequestWrapper +noop.sink.topics.SDNR-CL.events.custom.gson=org.onap.policy.sdnr.util.Serialization,gson + rules.groupId=${groupId} rules.artifactId=${artifactId} rules.version=${version} + diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.rest.json b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.rest.json index ee8e145b4..97506277e 100644 --- a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.rest.json +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.rest.json @@ -1,7 +1,7 @@ { "controller.name": "${artifactId}", - "ueb.source.topics": "${dcaeTopic},APPC-CL,APPC-LCM-WRITE", + "ueb.source.topics": "${dcaeTopic},APPC-CL,APPC-LCM-WRITE,SDNR-CL-RSP", "ueb.source.topics.${dcaeTopic}.servers": "${dcaeServers}", "ueb.source.topics.${dcaeTopic}.events": "org.onap.policy.controlloop.VirtualControlLoopEvent", @@ -18,7 +18,12 @@ "ueb.source.topics.APPC-LCM-WRITE.events.org.onap.policy.appclcm.LcmResponseWrapper.filter": "type=response", "ueb.source.topics.APPC-LCM-WRITE.events.custom.gson": "org.onap.policy.appclcm.util.Serialization,gson", - "noop.sink.topics": "APPC-CL,APPC-LCM-READ,POLICY-CL-MGT", + "ueb.source.topics.SDNR-CL-RSP.servers": "${dmaapServers}", + "ueb.source.topics.SDNR-CL-RSP.events": "org.onap.policy.sdnr.PciResponseWrapper", + "ueb.source.topics.SDNR-CL-RSP.events.org.onap.policy.sdnr.PciResponseWrapper.filter": "type=response", + "ueb.source.topics.SDNR-CL-RSP.events.custom.gson": "org.onap.policy.sdnr.util.Serialization,gson", + + "noop.sink.topics": "APPC-CL,APPC-LCM-READ,POLICY-CL-MGT,SDNR-CL", "noop.sink.topics.APPC-CL.servers": "${dmaapServers}", "noop.sink.topics.APPC-CL.events": "org.onap.policy.appc.Request", @@ -32,7 +37,12 @@ "noop.sink.topics.POLICY-CL-MGT.events": "org.onap.policy.controlloop.VirtualControlLoopNotification", "noop.sink.topics.POLICY-CL-MGT.events.custom.gson": "org.onap.policy.controlloop.util.Serialization,gson", + "noop.sink.topics.SDNR-CL.servers": "${dmaapServers}", + "noop.sink.topics.SDNR-CL.events": "org.onap.policy.sdnr.PciRequestWrapper", + "noop.sink.topics.SDNR-CL.events.custom.gson": "org.onap.policy.sdnr.util.Serialization,gson", + "rules.groupId": "${groupId}", "rules.artifactId": "${artifactId}", "rules.version": "${version}" + } diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.pcims.onset.json b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.pcims.onset.json new file mode 100644 index 000000000..0e67d3251 --- /dev/null +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.pcims.onset.json @@ -0,0 +1,18 @@ +{ + "closedLoopControlName": "ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459", + "closedLoopAlarmStart": 1510187409180, + "closedLoopEventClient": "microservice.PCI", + "closedLoopEventStatus": "ONSET", + "requestID": "9d2d790e-a5f0-11e8-98d0-529269fb1459", + "target_type": "VNF", + "target": "generic-vnf.vnf-id", + "AAI": { + "generic-vnf.is-closed-loop-disabled": "false", + "generic-vnf.prov-status": "ACTIVE", + "generic-vnf.vnf-id": "notused" + }, + "from": "PCIMS", + "version": "1.0.2", + "Action": "ModifyConfig", + "payload": "{ \"Configurations\":[ { \"data\":{ \"FAPService\":{ \"alias\":\"Cell1\", \"X0005b9Lte\" : { \"PhyCellIdInUse\" : \"35\", \"PnfName\" : \"cu1\" }, \"CellConfig\":{ \"LTE\":{ \"RAN\":{ \"Common\":{ \"CellIdentity\":\"1\" } } } } } } } ] }" +} diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.sdnr.success.json b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.sdnr.success.json new file mode 100644 index 000000000..74d7f60bb --- /dev/null +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.sdnr.success.json @@ -0,0 +1,23 @@ +{ + "body": { + "output": { + "CommonHeader": { + "TimeStamp": "2018-09-10T07:10:05.614Z", + "APIver": "1.0", + "RequestID": "9d2d790e-a5f0-11e8-98d0-529269fb1459", + "SubRequestID": "1", + "RequestTrack": [], + "Flags": [] + }, + "Status": { + "Code": 200, + "Value": "SUCCESS" + }, + "Payload": "{ \"Configurations\":[ { \"Status\": { \"Code\": 200, \"Value\": \"SUCCESS\" }, \"data\":{ \"FAPService\":{ \"alias\":\"Network1\", \"X0005b9Lte\" : { \"PnfName\" : \"cu1\" }, \"CellConfig\":{ \"LTE\":{ \"RAN\":{ \"Common\":{ \"CellIdentity\":\"1\" } } } } } } } ] }" + } + }, + "version": "1.0", + "rpc-name": "ModifyConfig", + "correlation-id": "9d2d790e-a5f0-11e8-98d0-529269fb1459-1", + "type": "response" +} diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.yaml b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.yaml new file mode 100644 index 000000000..0fe44e3d0 --- /dev/null +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.yaml @@ -0,0 +1,38 @@ +# Copyright 2018 Wipro Limited 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. +controlLoop: + version: 3.0.0 + controlLoopName: ${closedLoopControlName} + trigger_policy: unique-policy-id-123-modifyconfig + timeout: 1200 + abatement: false + +policies: + - id: unique-policy-id-123-modifyconfig + name: modify PCI config + description: + actor: SDNR + recipe: ModifyConfig + target: + # These fields are not used + resourceID: Eace933104d443b496b8.nodes.heat.vpg + type: VNF + retry: 0 + timeout: 300 + success: final_success + failure: final_failure + failure_timeout: final_failure_timeout + failure_retries: final_failure_retries + failure_exception: final_failure_exception + failure_guard: final_failure_guard diff --git a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl index 5e49010d7..48cfab24c 100644 --- a/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl +++ b/controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl @@ -41,6 +41,10 @@ import org.onap.policy.appclcm.LcmResponseWrapper; import org.onap.policy.appclcm.LcmRequest; import org.onap.policy.appclcm.LcmResponse; import org.onap.policy.appclcm.LcmCommonHeader; +import org.onap.policy.sdnr.PciRequestWrapper; +import org.onap.policy.sdnr.PciResponseWrapper; +import org.onap.policy.sdnr.PciRequest; +import org.onap.policy.sdnr.PciResponse; import org.onap.policy.vfc.VFCRequest; import org.onap.policy.vfc.VFCResponse; import org.onap.policy.vfc.VFCManager; @@ -591,6 +595,11 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" t.start(); } break; + case "SDNR": + if (request instanceof PciRequestWrapper) { + PolicyEngine.manager.deliver("SDNR-CL", request); + } + break; } } else { // @@ -1011,6 +1020,115 @@ rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP" retract($response); end +/* +* +* This rule responds to SDNR Response Events using the new interface provided by SDNR +* +*/ +rule "${policyName}.SDNR.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), + closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), + requestID == $event.getRequestId() ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), + onset.getRequestId() == $event.getRequestId() ) + $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), + requestID == $event.getRequestId().toString(), timerType == "Operation", !expired ) + $lock : TargetLock (requestID == $event.getRequestId()) + $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName()); + logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", + $params.getClosedLoopControlName(), drools.getRule().getName(), + $event, $manager, $operation, $lock, $operation, $opTimer, $response); + + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + logger.debug("{}: {}: operation finished - result={}", + $params.getClosedLoopControlName(), drools.getRule().getName(), + policyResult); + + // + // This Operation has completed, construct a notification showing our results. (DB write - end operation) + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.setFrom("policy"); + notification.setPolicyName(drools.getRule().getName()); + notification.setPolicyScope("${policyScope}"); + notification.setPolicyVersion("${policyVersion}"); + notification.setMessage($operation.getOperationHistory()); + notification.setHistory($operation.getHistory()); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.setNotification(ControlLoopNotificationType.OPERATION_SUCCESS); + } else { + notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE); + } + PolicyEngine.manager.deliver("POLICY-CL-MGT", notification); + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete()) { + // + // It is complete, remove it from memory + // + retract($operation); + // + // We must also retract the timer object + // NOTE: We could write a Rule to do this + // + retract($opTimer); + // + // Complete the operation + // + modify($manager) {finishOperation($operation)}; + } else { + // + // Just doing this will kick off the LOCKED rule again + // + modify($operation) {}; + } + } else { + // + // Its not finished yet (i.e. expecting more Response objects) + // + // Or possibly it is a leftover response that we timed the request out previously + // + } + // + // We are going to retract these objects from memory + // + retract($response); +end + +/* +* +* Clean Up any lingering SDNR reponses +* +*/ +rule "${policyName}.SDNR.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId ) + not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + + Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage()); + logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName()); + logger.debug("{}: {}: orphan SDNR response={}", + $params.getClosedLoopControlName(), drools.getRule().getName(), $id); + // + // Retract it + // + retract($response); +end + /* * * This rule responds to SO Response Events diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VpciControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VpciControlLoopTest.java new file mode 100644 index 000000000..37f55dc09 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VpciControlLoopTest.java @@ -0,0 +1,420 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2018 Wipro Limited 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.template.demo; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.IOException; +import java.net.URLEncoder; +import java.time.Instant; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; +import java.util.UUID; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; +import org.onap.policy.common.endpoints.event.comm.TopicListener; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.ControlLoopTargetType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.system.PolicyEngine; +import org.onap.policy.drools.utils.logging.LoggerUtil; +import org.onap.policy.sdnr.PciRequest; +import org.onap.policy.sdnr.PciRequestWrapper; +import org.onap.policy.sdnr.PciResponse; +import org.onap.policy.sdnr.PciResponseWrapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VpciControlLoopTest implements TopicListener { + + private static final Logger logger = LoggerFactory.getLogger(VpciControlLoopTest.class); + + private static List noopTopics; + + private static KieSession kieSession; + private static Util.Pair pair; + private UUID requestId; + + static { + /* Set environment properties */ + Util.setAaiProps(); + Util.setGuardProps(); + Util.setPuProp(); + LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "DEBUG"); + } + + /** + * Setup the simulator. + */ + @BeforeClass + public static void setUpSimulator() { + PolicyEngine.manager.configure(new Properties()); + assertTrue(PolicyEngine.manager.start()); + Properties noopSinkProperties = new Properties(); + noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "SDNR-CL,POLICY-CL-MGT"); + noopSinkProperties.put("noop.sink.topics.SDNR-CL.events", "org.onap.policy.sdnr.PciRequestWrapper"); + noopSinkProperties.put("noop.sink.topics.SDNR-CL.events.custom.gson", + "org.onap.policy.sdnr.util.Serialization,gson"); + noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events", + "org.onap.policy.controlloop.VirtualControlLoopNotification"); + noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson", + "org.onap.policy.controlloop.util.Serialization,gsonPretty"); + noopTopics = TopicEndpoint.manager.addTopicSinks(noopSinkProperties); + + EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "POLICY-CL-MGT", + "org.onap.policy.controlloop.VirtualControlLoopNotification", new JsonProtocolFilter(), null, null, + 1111); + EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "SDNR-CL", + "org.onap.policy.sdnr.PciRequestWrapper", new JsonProtocolFilter(), null, null, 1111); + try { + Util.buildAaiSim(); + Util.buildGuardSim(); + } catch (Exception e) { + fail(e.getMessage()); + } + /* + * Start the kie session + */ + try { + kieSession = startSession( + "../archetype-cl-amsterdam/src/main/resources/archetype-resources" + + "/src/main/resources/__closedLoopControlName__.drl", + "src/test/resources/yaml/policy_ControlLoop_vPCI.yaml", "type=operational", "CL_vPCI", "v3.0.0"); + } catch (IOException e) { + e.printStackTrace(); + logger.debug("Could not create kieSession"); + fail("Could not create kieSession"); + } + } + + /** + * Tear down the simulator. + */ + @AfterClass + public static void tearDownSimulator() { + /* + * Gracefully shut down the kie session + */ + kieSession.dispose(); + + PolicyEngine.manager.stop(); + HttpServletServer.factory.destroy(); + PolicyController.factory.shutdown(); + TopicEndpoint.manager.shutdown(); + } + + @Test + public void successTest() { + + /* + * Allows the PolicyEngine to callback to this object to notify that there is an + * event ready to be pulled from the queue + */ + for (TopicSink sink : noopTopics) { + assertTrue(sink.start()); + sink.register(this); + } + + /* + * Create a unique requestId + */ + requestId = UUID.randomUUID(); + + /* + * Simulate an onset event the policy engine will receive from DCAE to kick off + * processing through the rules + */ + sendEvent(pair.first, requestId, ControlLoopEventStatus.ONSET, true); + + kieSession.fireUntilHalt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + } + + @Test + public void aaiGetFailTest() { + + /* + * Allows the PolicyEngine to callback to this object to notify that there is an + * event ready to be pulled from the queue + */ + for (TopicSink sink : noopTopics) { + assertTrue(sink.start()); + sink.register(this); + } + + /* + * Create a unique requestId + */ + requestId = UUID.randomUUID(); + + /* + * Simulate an onset event the policy engine will receive from DCAE to kick off + * processing through the rules + */ + sendEvent(pair.first, requestId, ControlLoopEventStatus.ONSET, false); + + kieSession.fireUntilHalt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + } + + /** + * This method will start a kie session and instantiate the Policy Engine. + * + * @param droolsTemplate + * the DRL rules file + * @param yamlFile + * the yaml file containing the policies + * @param policyScope + * scope for policy + * @param policyName + * name of the policy + * @param policyVersion + * version of the policy + * @return the kieSession to be used to insert facts + * @throws IOException + * IO exception + */ + private static KieSession startSession(String droolsTemplate, String yamlFile, String policyScope, + String policyName, String policyVersion) throws IOException { + + /* + * Load policies from yaml + */ + pair = Util.loadYaml(yamlFile); + assertNotNull(pair); + assertNotNull(pair.first); + assertNotNull(pair.first.getControlLoop()); + assertNotNull(pair.first.getControlLoop().getControlLoopName()); + assertTrue(pair.first.getControlLoop().getControlLoopName().length() > 0); + + /* + * Construct a kie session + */ + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.first.getControlLoop().getControlLoopName(), policyScope, policyName, policyVersion, + URLEncoder.encode(pair.second, "UTF-8")); + + /* + * Retrieve the Policy Engine + */ + + logger.debug("======controlloop======"); + logger.debug(((ControlLoopPolicy) pair.first).toString()); + logger.debug("======policies======"); + logger.debug(URLEncoder.encode(pair.second, "UTF-8")); + logger.debug("============"); + + return kieSession; + } + + /* + * (non-Javadoc) + * + * @see + * org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang. + * String) + */ + @Override + public void onTopicEvent(CommInfrastructure commType, String topic, String event) { + logger.debug("\n============ onTopicEvent!!! ===========\n"); + logger.debug("topic: {}, event: {}", topic, event); + /* + * Pull the object that was sent out to DMAAP and make sure it is a + * ControlLoopNoticiation of type active + */ + Object obj = null; + if ("POLICY-CL-MGT".equals(topic)) { + obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event, + org.onap.policy.controlloop.VirtualControlLoopNotification.class); + } else if ("SDNR-CL".equals(topic)) { + obj = org.onap.policy.sdnr.util.Serialization.gsonJunit.fromJson(event, + org.onap.policy.sdnr.PciRequestWrapper.class); + } + assertNotNull(obj); + if (obj instanceof VirtualControlLoopNotification) { + VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj; + String policyName = notification.getPolicyName(); + logger.debug("Rule Fired: {}", policyName); + if (policyName.endsWith("EVENT")) { + assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification())); + } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) { + assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification())); + assertNotNull(notification.getMessage()); + assertTrue(notification.getMessage().startsWith("Sending guard query")); + } else if (policyName.endsWith("GUARD.RESPONSE")) { + assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification())); + assertNotNull(notification.getMessage()); + assertTrue(notification.getMessage().toLowerCase().endsWith("permit")); + } else if (policyName.endsWith("GUARD_PERMITTED")) { + assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification())); + assertNotNull(notification.getMessage()); + assertTrue(notification.getMessage().startsWith("actor=SDNR")); + } else if (policyName.endsWith("OPERATION.TIMEOUT")) { + kieSession.halt(); + logger.debug("The operation timed out"); + fail("Operation Timed Out"); + } else if (policyName.endsWith("SDNR.RESPONSE")) { + assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification())); + assertNotNull(notification.getMessage()); + assertTrue(notification.getMessage().startsWith("actor=SDNR")); + } else if (policyName.endsWith("EVENT.MANAGER")) { + if ("getFail".equals(notification.getAai().get("generic-vnf.vnf-id"))) { + assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification()); + kieSession.halt(); + } else { + assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notification.getNotification()); + kieSession.halt(); + } + } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) { + kieSession.halt(); + logger.debug("The control loop timed out"); + fail("Control Loop Timed Out"); + } + } else if (obj instanceof PciRequestWrapper) { + /* + * The request should be of type PciRequestWrapper and the subrequestid should + * be 1 + */ + PciRequestWrapper dmaapRequest = (PciRequestWrapper) obj; + PciRequest pciRequest = dmaapRequest.getBody(); + assertTrue(pciRequest.getCommonHeader().getSubRequestId().equals("1")); + + logger.debug("\n============ SDNR received the request!!! ===========\n"); + logger.debug("\n============ dmaapRequest ===========\n {} ", dmaapRequest); + logger.debug("\n============ pciRequest ===========\n {}", pciRequest); + + /* + * Simulate a success response from SDNR and insert the response into the + * working memory + */ + PciResponse pciResponse = new PciResponse(pciRequest); + pciResponse.getStatus().setCode(200); + pciResponse.getStatus().setValue("SUCCESS"); + StringBuilder sb = new StringBuilder(); + sb.append("{ \"Configurations\":[ { \"Status\": { \"Code\": 200, \"Value\":" + + " \"SUCCESS\" }, \"data\":{ \"FAPService\":{ \"alias\":" + + "\"Network1\", \"X0005b9Lte\" : { \"PnfName\" : \"cu1\" }, \"CellConfig\":" + + "{ \"LTE\":{ \"RAN\":{ \"Common\":{ \"CellIdentity\":" + "\"1\" } } } } } } } ] }"); + + pciResponse.setPayload(sb.toString()); + PciResponseWrapper dmaapResponse = new PciResponseWrapper(); + dmaapResponse.setBody(pciResponse); + dmaapResponse.setType("response"); + logger.debug("\n============ SDNR sending response!!! ===========\n"); + logger.debug("\n============ dmaapResponse ===========\n {}", dmaapResponse); + logger.debug("\n============ pciResponse ===========\n {}", pciResponse); + kieSession.insert(dmaapResponse); + } + } + + /** + * This method is used to simulate event messages from DCAE that start the + * control loop (onset message). + * + * @param policy + * the controlLoopName comes from the policy + * @param requestID + * the requestId for this event + * @param status + * could be onset + */ + protected void sendEvent(ControlLoopPolicy policy, UUID requestId, ControlLoopEventStatus status, + boolean isEnriched) { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName()); + event.setRequestId(requestId); + event.setTarget("generic-vnf.vnf-id"); + event.setTargetType(ControlLoopTargetType.VNF); + event.setClosedLoopAlarmStart(Instant.now()); + event.setAai(new HashMap<>()); + if (isEnriched) { + event.getAai().put("generic-vnf.is-closed-loop-disabled", "false"); + event.getAai().put("generic-vnf.prov-status", "ACTIVE"); + event.getAai().put("generic-vnf.vnf-id", "notused"); + } else { + event.getAai().put("generic-vnf.vnf-id", "getFail"); + } + event.setClosedLoopEventStatus(status); + StringBuilder sb = new StringBuilder(); + sb.append("{ \"Configurations\":[ { \"data\":{ \"FAPService\":" + + " { \"alias\":\"Cell1\", \"X0005b9Lte\" : { \"PhyCellIdInUse\" :" + + " \"35\", \"PnfName\" : \"cu1\" }, \"CellConfig\":{ \"LTE\":{ \"RAN\":" + + "{ \"Common\":{ \"CellIdentity\":\"1\" } } } } } } } ] }"); + + event.setPayload(sb.toString()); + logger.debug("\n============ Policy receiving ONSET event !!! ===========\n"); + logger.debug("\n============ event ===========\n {}", event); + kieSession.insert(event); + } + + /** + * This method will dump all the facts in the working memory. + * + * @param kieSession + * the session containing the facts + */ + public void dumpFacts(KieSession kieSession) { + logger.debug("Fact Count: {}", kieSession.getFactCount()); + for (FactHandle handle : kieSession.getFactHandles()) { + logger.debug("FACT: {}", handle); + } + } + +} diff --git a/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vPCI.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vPCI.yaml new file mode 100644 index 000000000..35cb2ac3d --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vPCI.yaml @@ -0,0 +1,38 @@ +# Copyright 2018 Wipro Limited 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. +controlLoop: + version: 3.0.0 + controlLoopName: ControlLoop-vPCI-fb41f388-a5f2-11e8-98d0-529269fb1459 + trigger_policy: unique-policy-id-123-modifyconfig + timeout: 1200 + abatement: false + +policies: + - id: unique-policy-id-123-modifyconfig + name: modify PCI config + description: + actor: SDNR + recipe: ModifyConfig + target: + # These fields are not used + resourceID: Eace933104d443b496b8.nodes.heat.vpg + type: VNF + retry: 0 + timeout: 300 + success: final_success + failure: final_failure + failure_timeout: final_failure_timeout + failure_retries: final_failure_retries + failure_exception: final_failure_exception + failure_guard: final_failure_guard -- cgit 1.2.3-korg