diff options
author | Pamela Dragosh <pdragosh@research.att.com> | 2017-09-07 10:16:09 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2017-09-07 10:16:09 +0000 |
commit | 37b497d346a65ee9de077fdb24bee73cfe19b50e (patch) | |
tree | ddc75f000cb86e3a426cf34d6031efbc14c8735e /controlloop/templates | |
parent | 69c83c9d56715f02b3165e3b24efc26ac13089d9 (diff) | |
parent | 7576237fd14304e987eb3c907d481f503dab8232 (diff) |
Merge "Add APPC LCM Interface"
Diffstat (limited to 'controlloop/templates')
10 files changed, 1134 insertions, 18 deletions
diff --git a/controlloop/templates/template.demo/pom.xml b/controlloop/templates/template.demo/pom.xml index c0aef2074..5436b5ebd 100644 --- a/controlloop/templates/template.demo/pom.xml +++ b/controlloop/templates/template.demo/pom.xml @@ -67,6 +67,18 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>appclcm</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>trafficgenerator</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>vfc</artifactId> <version>${project.version}</version> <scope>provided</scope> @@ -151,6 +163,12 @@ </dependency> <dependency> <groupId>org.onap.policy.drools-applications</groupId> + <artifactId>actor.appclcm</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.onap.policy.drools-applications</groupId> <artifactId>actor.vfc</artifactId> <version>${project.version}</version> <scope>provided</scope> 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 3bdeca1fc..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 @@ -27,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<String, String>(); + 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<String, String>(); + 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<String, String>(); + 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<ControlLoopPolicy, String> 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<ControlLoopPolicy, String> 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 |