From 7576237fd14304e987eb3c907d481f503dab8232 Mon Sep 17 00:00:00 2001 From: daniel Date: Fri, 11 Aug 2017 11:36:09 -0500 Subject: Add APPC LCM Interface The LCM model code and service provider code is implemented. This model code is now used for the vCPE use case scenario. The vFW use case is still using the legacy APPC API as request by APPC for Policy to use in R1. The APPC service provider now generates a demo legacy APPC request with pg-streams. An A&AI named query is implemented for the vFW use case. The code for obtaining the generic-vnf.vnf-id is not in use until we set up the A&AI simulator to work without having cyclical depenncies inside the POMs. JUnits for the vFW and vCPE use cases are now supported. These JUnits test the complete flow of each scenario. A&AI testing is not supported in the JUnit test yet. These JUnits use a target type of VM as VNF is not supported yet. This will be changed when the Target Lock supports VNF. Amended to fix Sonar blockers. Issue-ID: POLICY-104 Change-Id: I46869c5fd5094919da55ad563d608fe6d4b6fea7 Signed-off-by: Daniel Cruz --- .../resources/ControlLoop_Template_xacml_guard.drl | 123 +++++- .../policy/template/demo/AaiSimulatorTest.java | 21 +- .../template/demo/ControlLoopXacmlGuardTest.java | 53 ++- .../java/org/onap/policy/template/demo/Util.java | 4 + .../policy/template/demo/VCPEControlLoopTest.java | 441 +++++++++++++++++++++ .../policy/template/demo/VFWControlLoopTest.java | 435 ++++++++++++++++++++ .../resources/yaml/policy_ControlLoop_vCPE.yaml | 23 ++ .../resources/yaml/policy_ControlLoop_vFW.yaml | 28 ++ .../yaml/policy_guard_appc_modifyconfig.yaml | 26 ++ 9 files changed, 1136 insertions(+), 18 deletions(-) create mode 100644 controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java create mode 100644 controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java create mode 100644 controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml create mode 100644 controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml create mode 100644 controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml (limited to 'controlloop/templates/template.demo/src') diff --git a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl index 276e64b7d..aa1f1e977 100644 --- a/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl +++ b/controlloop/templates/template.demo/src/main/resources/ControlLoop_Template_xacml_guard.drl @@ -32,6 +32,11 @@ import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager; import org.onap.policy.appc.Request; import org.onap.policy.appc.Response; import org.onap.policy.appc.CommonHeader; +import org.onap.policy.appclcm.LCMRequestWrapper; +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.vfc.VFCRequest; import org.onap.policy.vfc.VFCManager; import org.onap.policy.guard.PolicyGuard; @@ -490,7 +495,7 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED" case "APPC": - if (request instanceof Request) { + if (request instanceof Request || request instanceof LCMRequestWrapper) { Engine.deliver("UEB", "APPC-CL", request); } break; @@ -771,6 +776,122 @@ rule "${policyName}.APPC.RESPONSE.CLEANUP" // retract($response); end + +/* +* +* This rule responds to APPC Response Events using the new LCM interface provided by appc +* +*/ +rule "${policyName}.APPC.LCM.RESPONSE" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), closedLoopEventStatus == ControlLoopEventStatus.ONSET ) + $manager : ControlLoopEventManager( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID ) + $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.closedLoopControlName, onset.requestID == $event.requestID ) + $opTimer : OperationTimer( closedLoopControlName == $event.closedLoopControlName, requestID == $event.requestID.toString() ) + $lock : TargetLock (requestID == $event.requestID) + $response : LCMResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.requestID ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + Logger.metrics($event); + Logger.metrics($manager); + Logger.metrics($operation); + Logger.metrics($opTimer); + Logger.metrics($lock); + Logger.metrics($response); + // + // Get the result of the operation + // + PolicyResult policyResult = $operation.onResponse($response); + if (policyResult != null) { + Logger.info("operation finished with result: " + policyResult); + // + // This Operation has completed, construct a notification showing our results. (DB write - end operation) + // + VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event); + notification.from = "policy"; + notification.policyName = drools.getRule().getName(); + notification.policyScope = "${policyScope}"; + notification.policyVersion = "${policyVersion}"; + notification.message = $operation.getOperationHistory(); + notification.history = $operation.getHistory(); + if (policyResult.equals(PolicyResult.SUCCESS)) { + notification.notification = ControlLoopNotificationType.OPERATION_SUCCESS; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } else { + notification.notification = ControlLoopNotificationType.OPERATION_FAILURE; + // + // Let interested parties know + // + Engine.deliver("UEB", "POLICY-CL-MGT", notification); + } + // + // Ensure the operation is complete + // + if ($operation.isOperationComplete() == true) { + // + // 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 LCM reponses +* +*/ +rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP" + when + $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" ) + $response : LCMResponseWrapper($id : getBody().getCommonHeader().getRequestId ) + not ( VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), requestID == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) + then + // + // Logging + // + Logger.info("------------------------------------------------------------------------------------------------"); + Logger.metrics(Instant.now() + " " + drools.getRule().getName() + " " + drools.getRule().getPackage()); + Logger.metrics($params); + // + // Retract it + // + retract($response); +end + /* * * This is the timer that manages the timeout for an individual operation. diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java index 73d50a5db..71c6e3a29 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/AaiSimulatorTest.java @@ -1,3 +1,23 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 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.template.demo; import static org.junit.Assert.assertNotNull; @@ -7,7 +27,6 @@ import java.util.UUID; import org.junit.AfterClass; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.aai.AAIGETResponse; import org.onap.policy.aai.AAINQF199.AAINQF199Manager; diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java index 23f03f7e8..8c0b99462 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopXacmlGuardTest.java @@ -32,14 +32,16 @@ import java.time.Instant; import java.util.HashMap; import java.util.UUID; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Ignore; import org.junit.Test; import org.kie.api.runtime.KieSession; import org.kie.api.runtime.rule.FactHandle; -import org.onap.policy.appc.Request; -import org.onap.policy.appc.Response; -import org.onap.policy.appc.ResponseCode; -import org.onap.policy.appc.ResponseValue; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; import org.onap.policy.controlloop.ControlLoopEventStatus; import org.onap.policy.controlloop.ControlLoopNotificationType; @@ -47,6 +49,7 @@ import org.onap.policy.controlloop.VirtualControlLoopEvent; import org.onap.policy.controlloop.VirtualControlLoopNotification; import org.onap.policy.controlloop.policy.ControlLoopPolicy; import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.http.server.HttpServletServer; import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; import org.onap.policy.guard.PolicyGuard; import org.slf4j.Logger; @@ -55,8 +58,22 @@ import org.slf4j.LoggerFactory; public class ControlLoopXacmlGuardTest { + @BeforeClass + public static void setUpSimulator() { + try { + Util.buildAaiSim(); + } catch (InterruptedException e) { + fail(e.getMessage()); + } + } + + @AfterClass + public static void tearDownSimulator() { + HttpServletServer.factory.destroy(); + } + private static final Logger logger = LoggerFactory.getLogger(ControlLoopXacmlGuardTest.class); - + @Test public void test() { try { @@ -216,8 +233,10 @@ public class ControlLoopXacmlGuardTest { obj = engine.subscribe("UEB", "APPC-CL"); assertNotNull(obj); - assertTrue(obj instanceof Request); - assertTrue(((Request)obj).CommonHeader.SubRequestID.equals("1")); + assertTrue(obj instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1")); logger.debug("\n============ APP-C Got request!!! ===========\n"); // @@ -232,11 +251,12 @@ public class ControlLoopXacmlGuardTest { // // Now we are going to success it // - Response response = new Response((Request) obj); - response.Status.Code = ResponseCode.SUCCESS.getValue(); - response.Status.Value = ResponseValue.SUCCESS.toString(); - response.Status.Description = "AppC success"; - kieSession.insert(response); + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("AppC success"); + dmaapResponse.setBody(appcResponse); + kieSession.insert(dmaapResponse); // // Give it some time to process // @@ -248,7 +268,7 @@ public class ControlLoopXacmlGuardTest { // // now wait for it to finish // - Thread.sleep(5000); + Thread.sleep(15000); // // Ensure they released the lock // @@ -288,6 +308,7 @@ public class ControlLoopXacmlGuardTest { Object fact = kieSession.getObject(handle); assertEquals("", "org.onap.policy.controlloop.Params", fact.getClass().getName()); } + kieSession.dispose(); } @@ -307,7 +328,7 @@ public class ControlLoopXacmlGuardTest { event.target = "vserver.vserver-name"; event.closedLoopAlarmStart = Instant.now().minusSeconds(5); event.closedLoopAlarmEnd = Instant.now(); - event.AAI = new HashMap(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.is-closed-loop-disabled", "false"); @@ -322,7 +343,7 @@ public class ControlLoopXacmlGuardTest { event.requestID = requestID; event.target = "vserver.vserver-name"; event.closedLoopAlarmStart = Instant.now(); - event.AAI = new HashMap(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.is-closed-loop-disabled", "false"); @@ -350,7 +371,7 @@ public class ControlLoopXacmlGuardTest { // // add some aai // - event.AAI = new HashMap(); + event.AAI = new HashMap<>(); event.AAI.put("cloud-region.identity-url", "foo"); event.AAI.put("vserver.selflink", "bar"); event.AAI.put("vserver.vserver-name", "vmfoo"); diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java index 61be1535e..502ef7c1d 100644 --- a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/Util.java @@ -239,6 +239,10 @@ public final class Util { "src/main/resources/frequency_limiter_template.xml", "src/test/resources/xacml/autogenerated_frequency_limiter_migrate.xml"); + PolicyGuardYamlToXacml.fromYamlToXacml("src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml", + "src/main/resources/frequency_limiter_template.xml", + "src/test/resources/xacml/autogenerated_frequency_limiter_modifyconfig.xml"); + PolicyGuardYamlToXacml.fromYamlToXacmlBlacklist("src/test/resources/yaml/policy_guard_appc_restart_blacklist.yaml", "src/main/resources/blacklist_template.xml", "src/test/resources/xacml/autogenerated_blacklist.xml"); diff --git a/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java new file mode 100644 index 000000000..a34ee6cd1 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VCPEControlLoopTest.java @@ -0,0 +1,441 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 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.template.demo; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.URLEncoder; +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.onap.policy.appclcm.LCMRequest; +import org.onap.policy.appclcm.LCMRequestWrapper; +import org.onap.policy.appclcm.LCMResponse; +import org.onap.policy.appclcm.LCMResponseWrapper; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; +import org.onap.policy.guard.PolicyGuard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VCPEControlLoopTest { + + private static final Logger logger = LoggerFactory.getLogger(VCPEControlLoopTest.class); + + private KieSession kieSession; + private Util.Pair pair; + private PolicyEngineJUnitImpl engine; + + @Test + public void successTest() { + + /* + * Start the kie session + */ + try { + kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", + "src/test/resources/yaml/policy_ControlLoop_vCPE.yaml", + "service=ServiceTest;resource=ResourceTest;type=operational", + "CL_vCPE", + "org.onap.closed_loop.ServiceTest:VNFS:1.0.0"); + } catch (IOException e) { + e.printStackTrace(); + logger.debug("Could not create kieSession"); + fail("Could not create kieSession"); + } + + /* + * Create a thread to continuously fire rules + * until main thread calls halt + */ + new Thread( new Runnable() { + @Override + public void run() { + kieSession.fireUntilHalt(); + } + } ).start(); + + /* + * Create a unique requestId and a unique trigger source + */ + UUID requestID = UUID.randomUUID(); + String triggerSourceName = "foobartriggersource36"; + + /* + * This will be the object returned from the PolicyEngine + */ + Object obj = null; + + /* + * Simulate an onset event the policy engine will + * receive from DCAE to kick off processing through + * the rules. + */ + try { + sendOnset(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("Unable to send onset event"); + fail("Unable to send onset event"); + } + + /* + * Pull the object that was sent out to DMAAP and make + * sure it is a ControlLoopNoticiation of type active + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE)); + + /* + * Give the control loop time to acquire a lock + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The fact should be ready to query guard now to see + * if a ModifyConfig recipe is allowed + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("\n\n####################### GOING TO QUERY GUARD about Restart!!!!!!"); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * Make sure the object is an instance of a ControlLoopNotification + * and is of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The guard response should be received at this point + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The object should be a ControlLoopNotification with type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + /* + * See if Guard permits this action, if it does + * not then the test should fail + */ + if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) { + + /* + * A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Obtain the request sent from the Policy Engine + */ + obj = engine.subscribe("UEB", "APPC-CL"); + assertNotNull(obj); + + /* + * The request should be of type LCMRequestWrapper + * and the subrequestid should be 1 + */ + assertTrue(obj instanceof LCMRequestWrapper); + LCMRequestWrapper dmaapRequest = (LCMRequestWrapper) obj; + LCMRequest appcRequest = dmaapRequest.getBody(); + assertTrue(appcRequest.getCommonHeader().getSubRequestId().equals("1")); + + logger.debug("\n============ APPC received the request!!! ===========\n"); + + /* + * Give some time for processing + */ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Simulate a success response from APPC and insert + * the response into the working memory + */ + LCMResponseWrapper dmaapResponse = new LCMResponseWrapper(); + LCMResponse appcResponse = new LCMResponse(appcRequest); + appcResponse.getStatus().setCode(400); + appcResponse.getStatus().setMessage("AppC success"); + dmaapResponse.setBody(appcResponse); + kieSession.insert(dmaapResponse); + + /* + * Give time for processing + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Make sure the next notification is delivered + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be + * an OPERATION_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS)); + + /* + * Now simulate the abatement sent from DCAE + */ + try { + sendAbatement(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e1) { + e1.printStackTrace(); + logger.debug("Abatement could not be sent"); + fail("Abatement could not be sent"); + } + + /* + * Give time to finish processing + */ + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * This should be the final notification from the Policy Engine + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be of type FINAL_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS)); + + /* + * One final check to make sure the lock is released + */ + assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID)); + } + else { + fail("Operation Denied by Guard"); + } + + /* + * This will stop the thread that is firing the rules + */ + kieSession.halt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + /* + * Gracefully shut down the kie session + */ + kieSession.dispose(); + } + + /** + * 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 + */ + private 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.a); + assertNotNull(pair.a.getControlLoop()); + assertNotNull(pair.a.getControlLoop().getControlLoopName()); + assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0); + + /* + * Construct a kie session + */ + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.a.getControlLoop().getControlLoopName(), + policyScope, + policyName, + policyVersion, + URLEncoder.encode(pair.b, "UTF-8")); + + /* + * Retrieve the Policy Engine + */ + engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine"); + + logger.debug("============"); + logger.debug(URLEncoder.encode(pair.b, "UTF-8")); + logger.debug("============"); + + return kieSession; + } + + /** + * 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 triggerSourceName + * @throws InterruptedException + */ + protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("vserver.vserver-name", "testGenericVnfName"); + event.AAI.put("generic-vnf.vnf-id", "testGenericVnfId"); + event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + kieSession.insert(event); + Thread.sleep(1000); + } + + /** + * This method is used to simulate event messages from DCAE + * that end the control loop (abatement message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now().minusSeconds(5); + event.closedLoopAlarmEnd = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ABATED; + 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/java/org/onap/policy/template/demo/VFWControlLoopTest.java b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java new file mode 100644 index 000000000..25920e8b5 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/VFWControlLoopTest.java @@ -0,0 +1,435 @@ +/*- + * ============LICENSE_START======================================================= + * demo + * ================================================================================ + * Copyright (C) 2017 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.template.demo; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.URLEncoder; +import java.time.Instant; +import java.util.HashMap; +import java.util.UUID; + +import org.junit.Test; +import org.kie.api.runtime.KieSession; +import org.kie.api.runtime.rule.FactHandle; +import org.onap.policy.appc.Request; +import org.onap.policy.appc.Response; +import org.onap.policy.appc.ResponseCode; +import org.onap.policy.controlloop.ControlLoopEventStatus; +import org.onap.policy.controlloop.ControlLoopNotificationType; +import org.onap.policy.controlloop.VirtualControlLoopEvent; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.policy.ControlLoopPolicy; +import org.onap.policy.controlloop.policy.TargetType; +import org.onap.policy.drools.impl.PolicyEngineJUnitImpl; +import org.onap.policy.guard.PolicyGuard; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VFWControlLoopTest { + + private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class); + + private KieSession kieSession; + private Util.Pair pair; + private PolicyEngineJUnitImpl engine; + + @Test + public void successTest() { + + /* + * Start the kie session + */ + try { + kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl", + "src/test/resources/yaml/policy_ControlLoop_vFW.yaml", + "service=ServiceDemo;resource=Res1Demo;type=operational", + "CL_vFW", + "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0"); + } catch (IOException e) { + e.printStackTrace(); + logger.debug("Could not create kieSession"); + fail("Could not create kieSession"); + } + + /* + * Create a thread to continuously fire rules + * until main thread calls halt + */ + new Thread( new Runnable() { + @Override + public void run() { + kieSession.fireUntilHalt(); + } + } ).start(); + + /* + * Create a unique requestId and a unique trigger source + */ + UUID requestID = UUID.randomUUID(); + String triggerSourceName = "foobartriggersource36"; + + /* + * This will be the object returned from the PolicyEngine + */ + Object obj = null; + + /* + * Simulate an onset event the policy engine will + * receive from DCAE to kick off processing through + * the rules + */ + try { + sendOnset(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("Unable to send onset event"); + fail("Unable to send onset event"); + } + + /* + * Pull the object that was sent out to DMAAP and make + * sure it is a ControlLoopNoticiation of type active + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE)); + + /* + * Give the control loop time to acquire a lock + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The fact should be ready to query guard now to see + * if a ModifyConfig recipe is allowed + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("\n\n####################### GOING TO QUERY GUARD about ModifyConfig!!!!!!"); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * Make sure the object is an instance of a ControlLoopNotification + * and is of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * The guard response should be received at this point + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The object should be a ControlLoopNotification with type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + /* + * See if Guard permits this action, if it does + * not then the test should fail + */ + if (((VirtualControlLoopNotification)obj).message.contains("Guard result: Permit")) { + + /* + * Obtain the ControlLoopNoticiation, it should be of type operation + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * A notification should be sent out of the Policy + * Engine at this point, it will be of type operation + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION)); + + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Obtain the request sent from the Policy Engine + */ + obj = engine.subscribe("UEB", "APPC-CL"); + assertNotNull(obj); + + /* + * The request should be of type Request + * and the subrequestid should be 1 + */ + assertTrue(obj instanceof Request); + assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1")); + + logger.debug("\n============ APPC received the request!!! ===========\n"); + + /* + * Give some time for processing + */ + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Simulate a success response from APPC and insert + * the response into the working memory + */ + Response appcResponse = new Response((Request)obj); + appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue(); + appcResponse.getStatus().Description = "AppC success"; + kieSession.insert(appcResponse); + + /* + * Give time for processing + */ + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * Make sure the next notification is delivered + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be + * an OPERATION_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS)); + + /* + * Now simulate the abatement sent from DCAE + */ + try { + sendAbatement(pair.a, requestID, triggerSourceName); + } catch (InterruptedException e1) { + e1.printStackTrace(); + logger.debug("Abatement could not be sent"); + fail("Abatement could not be sent"); + } + + /* + * Give time to finish processing + */ + try { + Thread.sleep(20000); + } catch (InterruptedException e) { + e.printStackTrace(); + logger.debug("An interrupt Exception was thrown"); + fail("An interrupt Exception was thrown"); + } + + /* + * This should be the final notification from the Policy Engine + */ + obj = engine.subscribe("UEB", "POLICY-CL-MGT"); + assertNotNull(obj); + logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message); + + /* + * The ControlLoopNotification should be of type FINAL_SUCCESS + */ + assertTrue(obj instanceof VirtualControlLoopNotification); + assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS)); + + /* + * One final check to make sure the lock is released + */ + assertFalse(PolicyGuard.isLocked(TargetType.VM, triggerSourceName, requestID)); + } + else { + fail("Operation Denied by Guard"); + } + + /* + * This will stop the thread that is firing the rules + */ + kieSession.halt(); + + /* + * The only fact in memory should be Params + */ + assertEquals(1, kieSession.getFactCount()); + + /* + * Print what's left in memory + */ + dumpFacts(kieSession); + + /* + * Gracefully shut down the kie session + */ + kieSession.dispose(); + } + + /** + * 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 + */ + private 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.a); + assertNotNull(pair.a.getControlLoop()); + assertNotNull(pair.a.getControlLoop().getControlLoopName()); + assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0); + + /* + * Construct a kie session + */ + final KieSession kieSession = Util.buildContainer(droolsTemplate, + pair.a.getControlLoop().getControlLoopName(), + policyScope, + policyName, + policyVersion, + URLEncoder.encode(pair.b, "UTF-8")); + + /* + * Retrieve the Policy Engine + */ + engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine"); + + logger.debug("============"); + logger.debug(URLEncoder.encode(pair.b, "UTF-8")); + logger.debug("============"); + + return kieSession; + } + + /** + * 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 triggerSourceName + * @throws InterruptedException + */ + protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("vserver.vserver-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ONSET; + kieSession.insert(event); + Thread.sleep(2000); + } + + /** + * This method is used to simulate event messages from DCAE + * that end the control loop (abatement message). + * + * @param policy the controlLoopName comes from the policy + * @param requestID the requestId for this event + * @param triggerSourceName + * @throws InterruptedException + */ + protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException { + VirtualControlLoopEvent event = new VirtualControlLoopEvent(); + event.closedLoopControlName = policy.getControlLoop().getControlLoopName(); + event.requestID = requestID; + event.target = "vserver.vserver-name"; + event.closedLoopAlarmStart = Instant.now().minusSeconds(5); + event.closedLoopAlarmEnd = Instant.now(); + event.AAI = new HashMap<>(); + event.AAI.put("cloud-region.identity-url", "foo"); + event.AAI.put("vserver.selflink", "bar"); + event.AAI.put("vserver.is-closed-loop-disabled", "false"); + event.AAI.put("generic-vnf.vnf-name", "testGenericVnfName"); + event.closedLoopEventStatus = ControlLoopEventStatus.ABATED; + 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_vCPE.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml new file mode 100644 index 000000000..de2ece4ed --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vCPE.yaml @@ -0,0 +1,23 @@ +controlLoop: + version: 2.0.0 + controlLoopName: ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e + trigger_policy: unique-policy-id-1-restart + timeout: 3600 + abatement: true + +policies: + - id: unique-policy-id-1-restart + name: Restart the VM + description: + actor: APPC + recipe: Restart + target: + type: VM + retry: 3 + timeout: 1200 + 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/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml new file mode 100644 index 000000000..e78b1ca33 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_ControlLoop_vFW.yaml @@ -0,0 +1,28 @@ +controlLoop: + version: 2.0.0 + controlLoopName: ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a + services: + - serviceInvariantUUID: 5cfe6f4a-41bc-4247-8674-ebd4b98e35cc + serviceUUID: 0f40bba5-986e-4b3c-803f-ddd1b7b25f24 + serviceName: 57e66ea7-0ed6-45c7-970f + trigger_policy: unique-policy-id-1-modifyConfig + timeout: 1200 + abatement: true + +policies: + - id: unique-policy-id-1-modifyConfig + name: modify packet gen config + description: + actor: APPC + recipe: ModifyConfig + target: + resourceID: Eace933104d443b496b8.nodes.heat.vpg + type: VM + 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/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml new file mode 100644 index 000000000..a94d4f231 --- /dev/null +++ b/controlloop/templates/template.demo/src/test/resources/yaml/policy_guard_appc_modifyconfig.yaml @@ -0,0 +1,26 @@ +guard: + version: 2.0.0 + +guards: + - id: unique_guard_6 + name: APPC 6 ModifyConfig + description: | + We only allow 2 ModifyConfig over 10 minute window during the day time hours (avoid midnight to 5am) + match_parameters: + controlLoopName: ControlLoop-Service123-cbed919f-2212-4ef7-8051-fe6308da1bda + actor: APPC + recipe: ModifyConfig + targets: + - s1 + - s2 + - foobartriggersource36 + - s3 + - testGenericVnfName + limit_constraints: + - freq_limit_per_target: 1 + time_window: + value: 10 + units: minute + active_time_range: + start: 00:00:00-05:00 + end: 23:59:59-05:00 \ No newline at end of file -- cgit 1.2.3-korg