2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.template.demo;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
28 import java.io.IOException;
29 import java.net.URLEncoder;
30 import java.time.Instant;
31 import java.util.HashMap;
32 import java.util.UUID;
34 import org.junit.AfterClass;
35 import org.junit.BeforeClass;
36 import org.junit.Test;
37 import org.kie.api.runtime.KieSession;
38 import org.kie.api.runtime.rule.FactHandle;
39 import org.onap.policy.appc.Request;
40 import org.onap.policy.appc.Response;
41 import org.onap.policy.appc.ResponseCode;
42 import org.onap.policy.controlloop.ControlLoopEventStatus;
43 import org.onap.policy.controlloop.ControlLoopNotificationType;
44 import org.onap.policy.controlloop.VirtualControlLoopEvent;
45 import org.onap.policy.controlloop.VirtualControlLoopNotification;
46 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
47 import org.onap.policy.controlloop.policy.TargetType;
48 import org.onap.policy.drools.http.server.HttpServletServer;
49 import org.onap.policy.drools.impl.PolicyEngineJUnitImpl;
50 import org.onap.policy.guard.PolicyGuard;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 public class VFWControlLoopTest {
56 private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class);
58 private KieSession kieSession;
59 private Util.Pair<ControlLoopPolicy, String> pair;
60 private PolicyEngineJUnitImpl engine;
63 /* Set environment properties */
69 public static void setUpSimulator() {
73 } catch (Exception e) {
79 public static void tearDownSimulator() {
80 HttpServletServer.factory.destroy();
84 public void successTest() {
87 * Start the kie session
90 kieSession = startSession("src/main/resources/ControlLoop_Template_xacml_guard.drl",
91 "src/test/resources/yaml/policy_ControlLoop_vFW.yaml",
92 "service=ServiceDemo;resource=Res1Demo;type=operational",
94 "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
95 } catch (IOException e) {
97 logger.debug("Could not create kieSession");
98 fail("Could not create kieSession");
102 * Create a thread to continuously fire rules
103 * until main thread calls halt
105 new Thread( new Runnable() {
108 kieSession.fireUntilHalt();
113 * Create a unique requestId and a unique trigger source
115 UUID requestID = UUID.randomUUID();
116 String triggerSourceName = "foobartriggersource36";
119 * This will be the object returned from the PolicyEngine
124 * Simulate an onset event the policy engine will
125 * receive from DCAE to kick off processing through
129 sendOnset(pair.a, requestID, triggerSourceName);
130 } catch (InterruptedException e) {
132 logger.debug("Unable to send onset event");
133 fail("Unable to send onset event");
137 * Pull the object that was sent out to DMAAP and make
138 * sure it is a ControlLoopNoticiation of type active
140 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
142 assertTrue(obj instanceof VirtualControlLoopNotification);
143 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.ACTIVE));
146 * Give the control loop time to acquire a lock
150 } catch (InterruptedException e) {
152 logger.debug("An interrupt Exception was thrown");
153 fail("An interrupt Exception was thrown");
157 * The fact should be ready to query guard now to see
158 * if a ModifyConfig recipe is allowed
160 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
162 logger.debug("\n\n####################### GOING TO QUERY GUARD about ModifyConfig!!!!!!");
163 logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
166 * Make sure the object is an instance of a ControlLoopNotification
167 * and is of type operation
169 assertTrue(obj instanceof VirtualControlLoopNotification);
170 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
174 } catch (InterruptedException e) {
176 logger.debug("An interrupt Exception was thrown");
177 fail("An interrupt Exception was thrown");
181 * The guard response should be received at this point
183 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
185 logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
188 * The object should be a ControlLoopNotification with type operation
190 assertTrue(obj instanceof VirtualControlLoopNotification);
191 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
194 * See if Guard permits this action, if it does
195 * not then the test should fail
197 if (((VirtualControlLoopNotification)obj).message.contains("PERMIT")) {
200 * Obtain the ControlLoopNoticiation, it should be of type operation
202 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
204 logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
207 * A notification should be sent out of the Policy
208 * Engine at this point, it will be of type operation
210 assertTrue(obj instanceof VirtualControlLoopNotification);
211 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION));
215 } catch (InterruptedException e) {
217 logger.debug("An interrupt Exception was thrown");
218 fail("An interrupt Exception was thrown");
222 * Obtain the request sent from the Policy Engine
224 obj = engine.subscribe("UEB", "APPC-CL");
228 * The request should be of type Request
229 * and the subrequestid should be 1
231 assertTrue(obj instanceof Request);
232 assertTrue(((Request)obj).getCommonHeader().SubRequestID.equals("1"));
234 logger.debug("\n============ APPC received the request!!! ===========\n");
237 * Give some time for processing
241 } catch (InterruptedException e) {
243 logger.debug("An interrupt Exception was thrown");
244 fail("An interrupt Exception was thrown");
248 * Simulate a success response from APPC and insert
249 * the response into the working memory
251 Response appcResponse = new Response((Request)obj);
252 appcResponse.getStatus().Code = ResponseCode.SUCCESS.getValue();
253 appcResponse.getStatus().Value = "SUCCESS";
254 kieSession.insert(appcResponse);
257 * Give time for processing
261 } catch (InterruptedException e) {
263 logger.debug("An interrupt Exception was thrown");
264 fail("An interrupt Exception was thrown");
268 * Make sure the next notification is delivered
270 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
272 logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
275 * The ControlLoopNotification should be
276 * an OPERATION_SUCCESS
278 assertTrue(obj instanceof VirtualControlLoopNotification);
279 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.OPERATION_SUCCESS));
282 * Now simulate the abatement sent from DCAE
285 sendAbatement(pair.a, requestID, triggerSourceName);
286 } catch (InterruptedException e1) {
287 e1.printStackTrace();
288 logger.debug("Abatement could not be sent");
289 fail("Abatement could not be sent");
293 * Give time to finish processing
297 } catch (InterruptedException e) {
299 logger.debug("An interrupt Exception was thrown");
300 fail("An interrupt Exception was thrown");
304 * This should be the final notification from the Policy Engine
306 obj = engine.subscribe("UEB", "POLICY-CL-MGT");
308 logger.debug("Rule: {} Message {}", ((VirtualControlLoopNotification)obj).policyName, ((VirtualControlLoopNotification)obj).message);
311 * The ControlLoopNotification should be of type FINAL_SUCCESS
313 assertTrue(obj instanceof VirtualControlLoopNotification);
314 assertTrue(((VirtualControlLoopNotification)obj).notification.equals(ControlLoopNotificationType.FINAL_SUCCESS));
317 * One final check to make sure the lock is released
319 assertFalse(PolicyGuard.isLocked(TargetType.VNF, triggerSourceName, requestID));
322 fail("Operation Denied by Guard");
326 * This will stop the thread that is firing the rules
331 * The only fact in memory should be Params
333 // assertEquals(1, kieSession.getFactCount());
334 if (kieSession.getFactCount() != 1L) {
335 logger.error("FACT count mismatch: 1 expected but there are {}", kieSession.getFactCount());
339 * Print what's left in memory
341 dumpFacts(kieSession);
344 * Gracefully shut down the kie session
346 kieSession.dispose();
350 * This method will start a kie session and instantiate
353 * @param droolsTemplate
356 * the yaml file containing the policies
361 * @param policyVersion
362 * version of the policy
363 * @return the kieSession to be used to insert facts
364 * @throws IOException
366 private KieSession startSession(String droolsTemplate,
370 String policyVersion) throws IOException {
373 * Load policies from yaml
375 pair = Util.loadYaml(yamlFile);
377 assertNotNull(pair.a);
378 assertNotNull(pair.a.getControlLoop());
379 assertNotNull(pair.a.getControlLoop().getControlLoopName());
380 assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
383 * Construct a kie session
385 final KieSession kieSession = Util.buildContainer(droolsTemplate,
386 pair.a.getControlLoop().getControlLoopName(),
390 URLEncoder.encode(pair.b, "UTF-8"));
393 * Retrieve the Policy Engine
395 engine = (PolicyEngineJUnitImpl) kieSession.getGlobal("Engine");
397 logger.debug("============");
398 logger.debug(URLEncoder.encode(pair.b, "UTF-8"));
399 logger.debug("============");
405 * This method is used to simulate event messages from DCAE
406 * that start the control loop (onset message).
408 * @param policy the controlLoopName comes from the policy
409 * @param requestID the requestId for this event
410 * @param triggerSourceName
411 * @throws InterruptedException
413 protected void sendOnset(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
414 VirtualControlLoopEvent event = new VirtualControlLoopEvent();
415 event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
416 event.requestID = requestID;
417 event.target = "generic-vnf.vnf-id";
418 event.closedLoopAlarmStart = Instant.now();
419 event.AAI = new HashMap<>();
420 event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
421 event.closedLoopEventStatus = ControlLoopEventStatus.ONSET;
422 kieSession.insert(event);
427 * This method is used to simulate event messages from DCAE
428 * that end the control loop (abatement message).
430 * @param policy the controlLoopName comes from the policy
431 * @param requestID the requestId for this event
432 * @param triggerSourceName
433 * @throws InterruptedException
435 protected void sendAbatement(ControlLoopPolicy policy, UUID requestID, String triggerSourceName) throws InterruptedException {
436 VirtualControlLoopEvent event = new VirtualControlLoopEvent();
437 event.closedLoopControlName = policy.getControlLoop().getControlLoopName();
438 event.requestID = requestID;
439 event.target = "generic-vnf.vnf-id";
440 event.closedLoopAlarmStart = Instant.now().minusSeconds(5);
441 event.closedLoopAlarmEnd = Instant.now();
442 event.AAI = new HashMap<>();
443 event.AAI.put("cloud-region.identity-url", "foo");
444 event.AAI.put("vserver.selflink", "bar");
445 event.AAI.put("vserver.is-closed-loop-disabled", "false");
446 event.AAI.put("generic-vnf.vnf-id", "testGenericVnfID");
447 event.closedLoopEventStatus = ControlLoopEventStatus.ABATED;
448 kieSession.insert(event);
452 * This method will dump all the facts in the working memory.
454 * @param kieSession the session containing the facts
456 public void dumpFacts(KieSession kieSession) {
457 logger.debug("Fact Count: {}", kieSession.getFactCount());
458 for (FactHandle handle : kieSession.getFactHandles()) {
459 logger.debug("FACT: {}", handle);