1da3ff70c350d0d4926e2079058efbbc018b34ae
[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         /*
157          * The only fact in memory should be Params
158          */
159         assertEquals(1, kieSession.getFactCount());
160
161         /*
162          * Print what's left in memory
163          */
164         dumpFacts(kieSession);
165     }
166
167     @Test
168     public void nullRequestTest() throws IOException {
169
170         /*
171          * Allows the PolicyEngine to callback to this object to notify that there is an event ready
172          * to be pulled from the queue
173          */
174         for (TopicSink sink : noopTopics) {
175             assertTrue(sink.start());
176             sink.register(this);
177         }
178
179         /*
180          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
181          * through the rules
182          */
183
184         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
185         event.setClosedLoopControlName(pair.first.getControlLoop().getControlLoopName());
186         event.setRequestId(UUID.randomUUID());
187         event.setClosedLoopEventClient("DCAE.HolmesInstance");
188         event.setTargetType(ControlLoopTargetType.VM);
189         event.setTarget("vserver.vserver-name");
190         event.setFrom("DCAE");
191         event.setClosedLoopAlarmStart(Instant.now());
192         event.setAai(new HashMap<String, String>());
193         event.getAai().put("vserver.vserver-name", "nullRequest");
194         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
195         kieSession.insert(event);
196
197         kieSession.fireUntilHalt();
198
199         /*
200          * The only fact in memory should be Params
201          */
202         assertEquals(1, kieSession.getFactCount());
203
204         /*
205          * Print what's left in memory
206          */
207         dumpFacts(kieSession);
208     }
209
210     /**
211      * This method will start a kie session and instantiate the Policy Engine.
212      *
213      * @param droolsTemplate the DRL rules file
214      * @param yamlFile the yaml file containing the policies
215      * @param policyScope scope for policy
216      * @param policyName name of the policy
217      * @param policyVersion version of the policy
218      * @return the kieSession to be used to insert facts
219      * @throws IOException IO Exception
220      */
221     private static KieSession startSession(String droolsTemplate, String yamlFile, String policyScope,
222             String policyName, String policyVersion) throws IOException {
223
224         /*
225          * Load policies from yaml
226          */
227         pair = Util.loadYaml(yamlFile);
228         assertNotNull(pair);
229         assertNotNull(pair.first);
230         assertNotNull(pair.first.getControlLoop());
231         assertNotNull(pair.first.getControlLoop().getControlLoopName());
232         assertTrue(pair.first.getControlLoop().getControlLoopName().length() > 0);
233
234         /*
235          * Construct a kie session
236          */
237         final KieSession kieSession = Util.buildContainer(droolsTemplate,
238                 pair.first.getControlLoop().getControlLoopName(),
239                 policyScope, policyName, policyVersion, URLEncoder.encode(pair.second, "UTF-8"));
240
241         /*
242          * Retrieve the Policy Engine
243          */
244
245         logger.debug("============");
246         logger.debug(URLEncoder.encode(pair.second, "UTF-8"));
247         logger.debug("============");
248
249         return kieSession;
250     }
251
252     /*
253      * (non-Javadoc)
254      *
255      * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
256      */
257     @Override
258     public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
259         /*
260          * Pull the object that was sent out to DMAAP and make sure it is a ControlLoopNoticiation
261          * of type active
262          */
263         Object obj = null;
264         if ("POLICY-CL-MGT".equals(topic)) {
265             obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event,
266                     VirtualControlLoopNotification.class);
267         }
268         assertNotNull(obj);
269         if (obj instanceof VirtualControlLoopNotification) {
270             VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
271             String policyName = notification.getPolicyName();
272             if (policyName.endsWith("EVENT")) {
273                 logger.debug("Rule Fired: " + notification.getPolicyName());
274                 assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification()));
275             } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
276                 logger.debug("Rule Fired: " + notification.getPolicyName());
277                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
278                 assertNotNull(notification.getMessage());
279                 assertTrue(notification.getMessage().startsWith("Sending guard query"));
280             } else if (policyName.endsWith("GUARD.RESPONSE")) {
281                 logger.debug("Rule Fired: " + notification.getPolicyName());
282                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
283                 assertNotNull(notification.getMessage());
284                 assertTrue(notification.getMessage().toLowerCase().endsWith("permit"));
285             } else if (policyName.endsWith("GUARD_PERMITTED")) {
286                 logger.debug("Rule Fired: " + notification.getPolicyName());
287                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
288                 assertNotNull(notification.getMessage());
289                 assertTrue(notification.getMessage().startsWith("actor=SDNC"));
290             } else if (policyName.endsWith("OPERATION.TIMEOUT")) {
291                 logger.debug("Rule Fired: " + notification.getPolicyName());
292                 kieSession.halt();
293                 logger.debug("The operation timed out");
294                 fail("Operation Timed Out");
295             } else if (policyName.endsWith("SDNC.RESPONSE")) {
296                 logger.debug("Rule Fired: " + notification.getPolicyName());
297                 assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification()));
298                 assertNotNull(notification.getMessage());
299                 assertTrue(notification.getMessage().startsWith("actor=SDNC"));
300             } else if (policyName.endsWith("EVENT.MANAGER")) {
301                 logger.debug("Rule Fired: " + notification.getPolicyName());
302                 if ("nullRequest".equals(notification.getAai().get("vserver.vserver-name"))) {
303                     assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification());
304                 } else {
305                     assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notification.getNotification());
306                 }
307                 kieSession.halt();
308             } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
309                 logger.debug("Rule Fired: " + notification.getPolicyName());
310                 kieSession.halt();
311                 logger.debug("The control loop timed out");
312                 fail("Control Loop Timed Out");
313             }
314         } else if (obj instanceof SdncRequest) {
315             logger.debug("\n============ SDNC received the request!!! ===========\n");
316         }
317     }
318
319     /**
320      * This method is used to simulate event messages from DCAE that start the control loop (onset
321      * message) or end the control loop (abatement message).
322      * 
323      * @param policy the controlLoopName comes from the policy
324      */
325     protected void sendEvent(ControlLoopPolicy policy) {
326         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
327         event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName());
328         event.setRequestId(UUID.randomUUID());
329         event.setClosedLoopEventClient("DCAE.HolmesInstance");
330         event.setTargetType(ControlLoopTargetType.VM);
331         event.setTarget("vserver.vserver-name");
332         event.setFrom("DCAE");
333         event.setClosedLoopAlarmStart(Instant.now());
334         event.setAai(new HashMap<String, String>());
335         event.getAai().put("vserver.vserver-name", "TBD");
336         event.getAai().put("globalSubscriberId", "e151059a-d924-4629-845f-264db19e50b4");
337         event.getAai().put("serviceType", "SOTN");
338         event.getAai().put("service-instance.service-instance-id", "service-instance-id-example-1");
339         event.getAai().put("network-information.network-id", "id");
340         event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
341         kieSession.insert(event);
342     }
343
344     /**
345      * Dumps the kie session facts.
346      * 
347      * @param kieSession input session
348      */
349     public static void dumpFacts(KieSession kieSession) {
350         logger.debug("Fact Count: " + kieSession.getFactCount());
351         for (FactHandle handle : kieSession.getFactHandles()) {
352             logger.debug("FACT: " + handle);
353         }
354     }
355 }
356