Add implementation for OOF PCI use case 52/70052/1
authorSaravanan A <saravanan.a75@wipro.com>
Tue, 9 Oct 2018 10:50:52 +0000 (16:20 +0530)
committerSaravanan A <saravanan.a75@wipro.com>
Tue, 9 Oct 2018 10:51:21 +0000 (16:21 +0530)
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<saravanan.a75@wipro.com>
12 files changed:
controlloop/common/feature-controlloop-amsterdam/pom.xml
controlloop/common/feature-controlloop-amsterdam/src/main/feature/config/amsterdam-controller.properties
controlloop/common/policy-yaml/src/test/java/org/onap/policy/controlloop/policy/ControlLoopPolicyTest.java
controlloop/common/policy-yaml/src/test/resources/v2.0.0/policy_ONAP_UseCase_vPCI.yaml [new file with mode: 0644]
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.properties
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/__artifactId__-controller.rest.json
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.pcims.onset.json [new file with mode: 0644]
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.sdnr.success.json [new file with mode: 0644]
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/config/vPCI.yaml [new file with mode: 0644]
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl
controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VpciControlLoopTest.java [new file with mode: 0644]
controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vPCI.yaml [new file with mode: 0644]

index 15f0c35..273d056 100644 (file)
             <artifactId>appclcm</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId>
+            <artifactId>sdnr</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.drools-applications.controlloop.common.model-impl</groupId>
             <artifactId>vfc</artifactId>
                 </exclusion>
             </exclusions>
         </dependency>
+        <dependency>
+            <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId>
+            <artifactId>actor.sdnr</artifactId>
+            <version>${project.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>guava</artifactId>
+                    <groupId>com.google.guava</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
         <dependency>
             <groupId>org.onap.policy.drools-applications.controlloop.common.actors</groupId>
             <artifactId>actor.so</artifactId>
index 0d50138..d7dc0c1 100644 (file)
@@ -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=
+
index a4d1baa..00c7005 100644 (file)
@@ -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 (file)
index 0000000..3d47b64
--- /dev/null
@@ -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
+
index 6b59b71..3e67dca 100644 (file)
@@ -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}
+
index ee8e145..9750627 100644 (file)
@@ -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",
        "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",
        "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 (file)
index 0000000..0e67d32
--- /dev/null
@@ -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 (file)
index 0000000..74d7f60
--- /dev/null
@@ -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 (file)
index 0000000..0fe44e3
--- /dev/null
@@ -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
index 5e49010..48cfab2 100644 (file)
@@ -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 (file)
index 0000000..37f55dc
--- /dev/null
@@ -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<? extends TopicSink> noopTopics;
+
+    private static KieSession kieSession;
+    private static Util.Pair<ControlLoopPolicy, String> 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 (file)
index 0000000..35cb2ac
--- /dev/null
@@ -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