ea9e85709dc594ab7a62eae5dd2463d097af4025
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2018 Huawei. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ============LICENSE_END=========================================================
17  */
18
19 package org.onap.policy.template.demo;
20
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.io.IOException;
27 import java.net.URLEncoder;
28 import java.time.Instant;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.Properties;
32 import java.util.UUID;
33
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.common.endpoints.event.comm.Topic.CommInfrastructure;
40 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
41 import org.onap.policy.common.endpoints.event.comm.TopicListener;
42 import org.onap.policy.common.endpoints.event.comm.TopicSink;
43 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
44 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
45 import org.onap.policy.controlloop.ControlLoopEventStatus;
46 import org.onap.policy.controlloop.ControlLoopNotificationType;
47 import org.onap.policy.controlloop.ControlLoopTargetType;
48 import org.onap.policy.controlloop.VirtualControlLoopEvent;
49 import org.onap.policy.controlloop.VirtualControlLoopNotification;
50 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
51 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
52 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
53 import org.onap.policy.drools.system.PolicyController;
54 import org.onap.policy.drools.system.PolicyEngine;
55 import org.onap.policy.drools.utils.logging.LoggerUtil;
56 import org.onap.policy.sdnc.SdncRequest;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60 public class CcvpnControlLoopTest implements TopicListener {
61
62     private static final Logger logger = LoggerFactory.getLogger(CcvpnControlLoopTest.class);
63
64     private static List<? extends TopicSink> noopTopics;
65
66     private static KieSession kieSession;
67     private static Util.Pair<ControlLoopPolicy, String> pair;
68
69     static {
70         /* Set environment properties */
71         Util.setAaiProps();
72         Util.setSdncProps();
73         LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO");
74     }
75
76     /**
77      * Setup the simulator.
78      */
79     @BeforeClass
80     public static void setUpSimulator() {
81         PolicyEngine.manager.configure(new Properties());
82         assertTrue(PolicyEngine.manager.start());
83         Properties noopSinkProperties = new Properties();
84         noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "POLICY-CL-MGT");
85         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events",
86                 "org.onap.policy.controlloop.VirtualControlLoopNotification");
87         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson",
88                 "org.onap.policy.controlloop.util.Serialization,gsonPretty");
89         noopTopics = TopicEndpoint.manager.addTopicSinks(noopSinkProperties);
90
91         EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "POLICY-CL-MGT",
92                 "org.onap.policy.controlloop.VirtualControlLoopNotification", new JsonProtocolFilter(),
93                                               null, null,1111);
94
95         try {
96             Util.buildAaiSim();
97             Util.buildSdncSim();
98         } catch (Exception e) {
99             fail(e.getMessage());
100         }
101
102         /*
103          *
104          * Start the kie session
105          */
106         try {
107             kieSession = startSession(
108                     "../archetype-cl-amsterdam/src/main/resources/archetype-resources/"
109                     + "src/main/resources/__closedLoopControlName__.drl",
110                     "src/test/resources/yaml/policy_ControlLoop_CCVPN.yaml", "type=operational", "Connectivity Reroute",
111                     "2.0.0");
112         } catch (IOException e) {
113             e.printStackTrace();
114             logger.debug("Could not create kieSession");
115             fail("Could not create kieSession");
116         }
117     }
118
119     /**
120      * Tear down the simulator.
121      */
122     @AfterClass
123     public static void tearDownSimulator() {
124
125         /*
126          * Gracefully shut down the kie session
127          */
128         kieSession.dispose();
129
130         PolicyEngine.manager.stop();
131         HttpServletServer.factory.destroy();
132         PolicyController.factory.shutdown();
133         TopicEndpoint.manager.shutdown();
134     }
135
136     @Test
137     public void successTest() throws IOException {
138
139         /*
140          * Allows the PolicyEngine to callback to this object to notify that there is an event ready
141          * to be pulled from the queue
142          */
143         for (TopicSink sink : noopTopics) {
144             assertTrue(sink.start());
145             sink.register(this);
146         }
147
148         /*
149          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
150          * through the rules
151          */
152         sendEvent(pair.first);
153
154         kieSession.fireUntilHalt();
155         
156         // allow object clean-up
157         kieSession.fireAllRules();
158
159         /*
160          * The only fact in memory should be Params
161          */
162         assertEquals(1, kieSession.getFactCount());
163
164         /*
165          * Print what's left in memory
166          */
167         dumpFacts(kieSession);
168     }
169
170     @Test
171     public void nullRequestTest() throws IOException {
172
173         /*
174          * Allows the PolicyEngine to callback to this object to notify that there is an event ready
175          * to be pulled from the queue
176          */
177         for (TopicSink sink : noopTopics) {
178             assertTrue(sink.start());
179             sink.register(this);
180         }
181
182         /*
183          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
184          * through the rules
185          */
186
187         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
188         event.setClosedLoopControlName(pair.first.getControlLoop().getControlLoopName());
189         event.setRequestId(UUID.randomUUID());
190         event.setClosedLoopEventClient("DCAE.HolmesInstance");
191         event.setTargetType(ControlLoopTargetType.VM);
192         event.setTarget("vserver.vserver-name");
193         event.setFrom("DCAE");
194         event.setClosedLoopAlarmStart(Instant.now());
195         event.setAai(new HashMap<String, String>());
196         event.getAai().put("vserver.vserver-name", "nullRequest");
197         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
198         kieSession.insert(event);
199
200         kieSession.fireUntilHalt();
201         
202         // allow object clean-up
203         kieSession.fireAllRules();
204
205         /*
206          * The only fact in memory should be Params
207          */
208         assertEquals(1, kieSession.getFactCount());
209
210         /*
211          * Print what's left in memory
212          */
213         dumpFacts(kieSession);
214     }
215
216     /**
217      * This method will start a kie session and instantiate the Policy Engine.
218      *
219      * @param droolsTemplate the DRL rules file
220      * @param yamlFile the yaml file containing the policies
221      * @param policyScope scope for policy
222      * @param policyName name of the policy
223      * @param policyVersion version of the policy
224      * @return the kieSession to be used to insert facts
225      * @throws IOException IO Exception
226      */
227     private static KieSession startSession(String droolsTemplate, String yamlFile, String policyScope,
228             String policyName, String policyVersion) throws IOException {
229
230         /*
231          * Load policies from yaml
232          */
233         pair = Util.loadYaml(yamlFile);
234         assertNotNull(pair);
235         assertNotNull(pair.first);
236         assertNotNull(pair.first.getControlLoop());
237         assertNotNull(pair.first.getControlLoop().getControlLoopName());
238         assertTrue(pair.first.getControlLoop().getControlLoopName().length() > 0);
239
240         /*
241          * Construct a kie session
242          */
243         final KieSession kieSession = Util.buildContainer(droolsTemplate,
244                 pair.first.getControlLoop().getControlLoopName(),
245                 policyScope, policyName, policyVersion, URLEncoder.encode(pair.second, "UTF-8"));
246
247         /*
248          * Retrieve the Policy Engine
249          */
250
251         logger.debug("============");
252         logger.debug(URLEncoder.encode(pair.second, "UTF-8"));
253         logger.debug("============");
254
255         return kieSession;
256     }
257
258     /*
259      * (non-Javadoc)
260      *
261      * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
262      */
263     @Override
264     public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
265         /*
266          * Pull the object that was sent out to DMAAP and make sure it is a ControlLoopNoticiation
267          * of type active
268          */
269         Object obj = null;
270         if ("POLICY-CL-MGT".equals(topic)) {
271             obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event,
272                     VirtualControlLoopNotification.class);
273         }
274         assertNotNull(obj);
275         if (obj instanceof VirtualControlLoopNotification) {
276             VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
277             String policyName = notification.getPolicyName();
278             if (policyName.endsWith("EVENT")) {
279                 logger.debug("Rule Fired: " + notification.getPolicyName());
280                 assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification()));
281             } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
282                 logger.debug("Rule Fired: " + notification.getPolicyName());
283                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
284                 assertNotNull(notification.getMessage());
285                 assertTrue(notification.getMessage().startsWith("Sending guard query"));
286             } else if (policyName.endsWith("GUARD.RESPONSE")) {
287                 logger.debug("Rule Fired: " + notification.getPolicyName());
288                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
289                 assertNotNull(notification.getMessage());
290                 assertTrue(notification.getMessage().toLowerCase().endsWith("permit"));
291             } else if (policyName.endsWith("GUARD_PERMITTED")) {
292                 logger.debug("Rule Fired: " + notification.getPolicyName());
293                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
294                 assertNotNull(notification.getMessage());
295                 assertTrue(notification.getMessage().startsWith("actor=SDNC"));
296             } else if (policyName.endsWith("OPERATION.TIMEOUT")) {
297                 logger.debug("Rule Fired: " + notification.getPolicyName());
298                 kieSession.halt();
299                 logger.debug("The operation timed out");
300                 fail("Operation Timed Out");
301             } else if (policyName.endsWith("SDNC.RESPONSE")) {
302                 logger.debug("Rule Fired: " + notification.getPolicyName());
303                 assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification()));
304                 assertNotNull(notification.getMessage());
305                 assertTrue(notification.getMessage().startsWith("actor=SDNC"));
306             } else if (policyName.endsWith("EVENT.MANAGER")) {
307                 logger.debug("Rule Fired: " + notification.getPolicyName());
308                 if ("nullRequest".equals(notification.getAai().get("vserver.vserver-name"))) {
309                     assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification());
310                 } else {
311                     assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notification.getNotification());
312                 }
313                 kieSession.halt();
314             } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
315                 logger.debug("Rule Fired: " + notification.getPolicyName());
316                 kieSession.halt();
317                 logger.debug("The control loop timed out");
318                 fail("Control Loop Timed Out");
319             }
320         } else if (obj instanceof SdncRequest) {
321             logger.debug("\n============ SDNC received the request!!! ===========\n");
322         }
323     }
324
325     /**
326      * This method is used to simulate event messages from DCAE that start the control loop (onset
327      * message) or end the control loop (abatement message).
328      * 
329      * @param policy the controlLoopName comes from the policy
330      */
331     protected void sendEvent(ControlLoopPolicy policy) {
332         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
333         event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName());
334         event.setRequestId(UUID.randomUUID());
335         event.setClosedLoopEventClient("DCAE.HolmesInstance");
336         event.setTargetType(ControlLoopTargetType.VM);
337         event.setTarget("vserver.vserver-name");
338         event.setFrom("DCAE");
339         event.setClosedLoopAlarmStart(Instant.now());
340         event.setAai(new HashMap<String, String>());
341         event.getAai().put("vserver.vserver-name", "TBD");
342         event.getAai().put("globalSubscriberId", "e151059a-d924-4629-845f-264db19e50b4");
343         event.getAai().put("serviceType", "SOTN");
344         event.getAai().put("service-instance.service-instance-id", "service-instance-id-example-1");
345         event.getAai().put("network-information.network-id", "id");
346         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
347         kieSession.insert(event);
348     }
349
350     /**
351      * Dumps the kie session facts.
352      * 
353      * @param kieSession input session
354      */
355     public static void dumpFacts(KieSession kieSession) {
356         logger.debug("Fact Count: " + kieSession.getFactCount());
357         for (FactHandle handle : kieSession.getFactHandles()) {
358             logger.debug("FACT: " + handle);
359         }
360     }
361 }
362