8cbb4d69db65179d138f401c1501ce482a7ebe45
[policy/drools-applications.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * demo
4  * ================================================================================
5  * Copyright (C) 2018 Wipro Limited Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.template.demo;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import java.io.IOException;
30 import java.net.URLEncoder;
31 import java.time.Instant;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Properties;
35 import java.util.UUID;
36
37 import org.junit.AfterClass;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.kie.api.runtime.KieSession;
41 import org.kie.api.runtime.rule.FactHandle;
42 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
43 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
44 import org.onap.policy.common.endpoints.event.comm.TopicListener;
45 import org.onap.policy.common.endpoints.event.comm.TopicSink;
46 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
47 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
48 import org.onap.policy.controlloop.ControlLoopEventStatus;
49 import org.onap.policy.controlloop.ControlLoopNotificationType;
50 import org.onap.policy.controlloop.ControlLoopTargetType;
51 import org.onap.policy.controlloop.VirtualControlLoopEvent;
52 import org.onap.policy.controlloop.VirtualControlLoopNotification;
53 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
54 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
55 import org.onap.policy.drools.protocol.coders.EventProtocolParams;
56 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
57 import org.onap.policy.drools.system.PolicyController;
58 import org.onap.policy.drools.system.PolicyEngine;
59 import org.onap.policy.drools.utils.logging.LoggerUtil;
60 import org.onap.policy.sdnr.PciRequest;
61 import org.onap.policy.sdnr.PciRequestWrapper;
62 import org.onap.policy.sdnr.PciResponse;
63 import org.onap.policy.sdnr.PciResponseWrapper;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
66
67 public class VpciControlLoopTest implements TopicListener {
68
69     private static final Logger logger = LoggerFactory.getLogger(VpciControlLoopTest.class);
70
71     private static List<? extends TopicSink> noopTopics;
72
73     private static KieSession kieSession;
74     private static SupportUtil.Pair<ControlLoopPolicy, String> pair;
75     private UUID requestId;
76
77     static {
78         /* Set environment properties */
79         SupportUtil.setAaiProps();
80         SupportUtil.setGuardProps();
81         SupportUtil.setPuProp();
82         LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "DEBUG");
83     }
84
85     /**
86      * Setup the simulator.
87      */
88     @BeforeClass
89     public static void setUpSimulator() {
90         PolicyEngine.manager.configure(new Properties());
91         assertTrue(PolicyEngine.manager.start());
92         Properties noopSinkProperties = new Properties();
93         noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "SDNR-CL,POLICY-CL-MGT");
94         noopSinkProperties.put("noop.sink.topics.SDNR-CL.events", "org.onap.policy.sdnr.PciRequestWrapper");
95         noopSinkProperties.put("noop.sink.topics.SDNR-CL.events.custom.gson",
96                 "org.onap.policy.sdnr.util.Serialization,gson");
97         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events",
98                 "org.onap.policy.controlloop.VirtualControlLoopNotification");
99         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson",
100                 "org.onap.policy.controlloop.util.Serialization,gsonPretty");
101         noopTopics = TopicEndpoint.manager.addTopicSinks(noopSinkProperties);
102
103         EventProtocolCoder.manager.addEncoder(EventProtocolParams.builder()
104                 .groupId("junit.groupId")
105                 .artifactId("junit.artifactId")
106                 .topic("POLICY-CL-MGT")
107                 .eventClass("org.onap.policy.controlloop.VirtualControlLoopNotification")
108                 .protocolFilter(new JsonProtocolFilter())
109                 .customGsonCoder(null)
110                 .customJacksonCoder(null)
111                 .modelClassLoaderHash(1111));
112         EventProtocolCoder.manager.addEncoder(EventProtocolParams.builder()
113                 .groupId("junit.groupId")
114                 .artifactId("junit.artifactId")
115                 .topic("SDNR-CL")
116                 .eventClass("org.onap.policy.sdnr.PciRequestWrapper")
117                 .protocolFilter(new JsonProtocolFilter())
118                 .customGsonCoder(null)
119                 .customJacksonCoder(null)
120                 .modelClassLoaderHash(1111));
121         try {
122             SupportUtil.buildAaiSim();
123             SupportUtil.buildGuardSim();
124         } catch (Exception e) {
125             fail(e.getMessage());
126         }
127         /*
128          * Start the kie session
129          */
130         try {
131             kieSession = startSession(
132                     "../archetype-cl-amsterdam/src/main/resources/archetype-resources"
133                             + "/src/main/resources/__closedLoopControlName__.drl",
134                     "src/test/resources/yaml/policy_ControlLoop_vPCI.yaml", "type=operational", "CL_vPCI", "v3.0.0");
135         } catch (IOException e) {
136             e.printStackTrace();
137             logger.debug("Could not create kieSession");
138             fail("Could not create kieSession");
139         }
140     }
141
142     /**
143      * Tear down the simulator.
144      */
145     @AfterClass
146     public static void tearDownSimulator() {
147         /*
148          * Gracefully shut down the kie session
149          */
150         kieSession.dispose();
151
152         PolicyEngine.manager.stop();
153         HttpServletServer.factory.destroy();
154         PolicyController.factory.shutdown();
155         TopicEndpoint.manager.shutdown();
156     }
157
158     @Test
159     public void successTest() {
160
161         /*
162          * Allows the PolicyEngine to callback to this object to notify that there is an
163          * event ready to be pulled from the queue
164          */
165         for (TopicSink sink : noopTopics) {
166             assertTrue(sink.start());
167             sink.register(this);
168         }
169
170         /*
171          * Create a unique requestId
172          */
173         requestId = UUID.randomUUID();
174
175         /*
176          * Simulate an onset event the policy engine will receive from DCAE to kick off
177          * processing through the rules
178          */
179         sendEvent(pair.first, requestId, ControlLoopEventStatus.ONSET, true);
180
181         kieSession.fireUntilHalt();
182         
183         // allow object clean-up
184         kieSession.fireAllRules();
185
186         /*
187          * The only fact in memory should be Params
188          */
189         assertEquals(1, kieSession.getFactCount());
190
191         /*
192          * Print what's left in memory
193          */
194         dumpFacts(kieSession);
195
196     }
197
198     @Test
199     public void aaiGetFailTest() {
200
201         /*
202          * Allows the PolicyEngine to callback to this object to notify that there is an
203          * event ready to be pulled from the queue
204          */
205         for (TopicSink sink : noopTopics) {
206             assertTrue(sink.start());
207             sink.register(this);
208         }
209
210         /*
211          * Create a unique requestId
212          */
213         requestId = UUID.randomUUID();
214
215         /*
216          * Simulate an onset event the policy engine will receive from DCAE to kick off
217          * processing through the rules
218          */
219         sendEvent(pair.first, requestId, ControlLoopEventStatus.ONSET, false);
220
221         kieSession.fireUntilHalt();
222         
223         // allow object clean-up
224         kieSession.fireAllRules();
225
226         /*
227          * The only fact in memory should be Params
228          */
229         assertEquals(1, kieSession.getFactCount());
230
231         /*
232          * Print what's left in memory
233          */
234         dumpFacts(kieSession);
235
236     }
237
238     /**
239      * This method will start a kie session and instantiate the Policy Engine.
240      * 
241      * @param droolsTemplate
242      *            the DRL rules file
243      * @param yamlFile
244      *            the yaml file containing the policies
245      * @param policyScope
246      *            scope for policy
247      * @param policyName
248      *            name of the policy
249      * @param policyVersion
250      *            version of the policy
251      * @return the kieSession to be used to insert facts
252      * @throws IOException
253      *             IO exception
254      */
255     private static KieSession startSession(String droolsTemplate, String yamlFile, String policyScope,
256             String policyName, String policyVersion) throws IOException {
257
258         /*
259          * Load policies from yaml
260          */
261         pair = SupportUtil.loadYaml(yamlFile);
262         assertNotNull(pair);
263         assertNotNull(pair.first);
264         assertNotNull(pair.first.getControlLoop());
265         assertNotNull(pair.first.getControlLoop().getControlLoopName());
266         assertTrue(pair.first.getControlLoop().getControlLoopName().length() > 0);
267
268         /*
269          * Construct a kie session
270          */
271         final KieSession kieSession = SupportUtil.buildContainer(droolsTemplate,
272                 pair.first.getControlLoop().getControlLoopName(), policyScope, policyName, policyVersion,
273                 URLEncoder.encode(pair.second, "UTF-8"));
274
275         /*
276          * Retrieve the Policy Engine
277          */
278
279         logger.debug("======controlloop======");
280         logger.debug(((ControlLoopPolicy) pair.first).toString());
281         logger.debug("======policies======");
282         logger.debug(URLEncoder.encode(pair.second, "UTF-8"));
283         logger.debug("============");
284
285         return kieSession;
286     }
287
288     /*
289      * (non-Javadoc)
290      * 
291      * @see
292      * org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.
293      * String)
294      */
295     @Override
296     public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
297         logger.debug("\n============ onTopicEvent!!! ===========\n");
298         logger.debug("topic: {}, event: {}", topic, event);
299         /*
300          * Pull the object that was sent out to DMAAP and make sure it is a
301          * ControlLoopNoticiation of type active
302          */
303         Object obj = null;
304         if ("POLICY-CL-MGT".equals(topic)) {
305             obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event,
306                     org.onap.policy.controlloop.VirtualControlLoopNotification.class);
307         } else if ("SDNR-CL".equals(topic)) {
308             obj = org.onap.policy.sdnr.util.Serialization.gsonJunit.fromJson(event,
309                     org.onap.policy.sdnr.PciRequestWrapper.class);
310         }
311         assertNotNull(obj);
312         if (obj instanceof VirtualControlLoopNotification) {
313             VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
314             String policyName = notification.getPolicyName();
315             logger.debug("Rule Fired: {}", policyName);
316             if (policyName.endsWith("EVENT")) {
317                 assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
318             } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
319                 assertEquals(ControlLoopNotificationType.OPERATION, notification.getNotification());
320                 assertNotNull(notification.getMessage());
321                 assertTrue(notification.getMessage().startsWith("Sending guard query"));
322             } else if (policyName.endsWith("GUARD.RESPONSE")) {
323                 assertEquals(ControlLoopNotificationType.OPERATION, notification.getNotification());
324                 assertNotNull(notification.getMessage());
325                 assertTrue(notification.getMessage().toLowerCase().endsWith("permit"));
326             } else if (policyName.endsWith("GUARD_PERMITTED")) {
327                 assertEquals(ControlLoopNotificationType.OPERATION, notification.getNotification());
328                 assertNotNull(notification.getMessage());
329                 assertTrue(notification.getMessage().startsWith("actor=SDNR"));
330             } else if (policyName.endsWith("OPERATION.TIMEOUT")) {
331                 kieSession.halt();
332                 logger.debug("The operation timed out");
333                 fail("Operation Timed Out");
334             } else if (policyName.endsWith("SDNR.RESPONSE")) {
335                 assertEquals(ControlLoopNotificationType.OPERATION_SUCCESS, notification.getNotification());
336                 assertNotNull(notification.getMessage());
337                 assertTrue(notification.getMessage().startsWith("actor=SDNR"));
338             } else if (policyName.endsWith("EVENT.MANAGER")) {
339                 if ("getFail".equals(notification.getAai().get("generic-vnf.vnf-id"))) {
340                     assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification());
341                     kieSession.halt();
342                 } else {
343                     assertEquals(ControlLoopNotificationType.FINAL_SUCCESS, notification.getNotification());
344                     kieSession.halt();
345                 }
346             } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
347                 kieSession.halt();
348                 logger.debug("The control loop timed out");
349                 fail("Control Loop Timed Out");
350             }
351         } else if (obj instanceof PciRequestWrapper) {
352             /*
353              * The request should be of type PciRequestWrapper and the subrequestid should
354              * be 1
355              */
356             PciRequestWrapper dmaapRequest = (PciRequestWrapper) obj;
357             PciRequest pciRequest = dmaapRequest.getBody();
358             assertEquals("1", pciRequest.getCommonHeader().getSubRequestId());
359
360             logger.debug("\n============ SDNR received the request!!! ===========\n");
361             logger.debug("\n============ dmaapRequest ===========\n {} ", dmaapRequest);
362             logger.debug("\n============ pciRequest ===========\n {}", pciRequest);
363
364             /*
365              * Simulate a success response from SDNR and insert the response into the
366              * working memory
367              */
368             PciResponse pciResponse = new PciResponse(pciRequest);
369             pciResponse.getStatus().setCode(200);
370             pciResponse.getStatus().setValue("SUCCESS");
371             StringBuilder sb = new StringBuilder();
372             sb.append("{ \"Configurations\":[ { \"Status\": { \"Code\": 200, \"Value\":"
373                     + " \"SUCCESS\" }, \"data\":{ \"FAPService\":{ \"alias\":"
374                     + "\"Network1\", \"X0005b9Lte\" : { \"PnfName\" : \"cu1\" }, \"CellConfig\":"
375                     + "{ \"LTE\":{ \"RAN\":{ \"Common\":{ \"CellIdentity\":" + "\"1\" } } } } } } } ] }");
376
377             pciResponse.setPayload(sb.toString());
378             PciResponseWrapper dmaapResponse = new PciResponseWrapper();
379             dmaapResponse.setBody(pciResponse);
380             dmaapResponse.setType("response");
381             logger.debug("\n============ SDNR sending response!!! ===========\n");
382             logger.debug("\n============ dmaapResponse ===========\n {}", dmaapResponse);
383             logger.debug("\n============ pciResponse ===========\n {}", pciResponse);
384             kieSession.insert(dmaapResponse);
385         }
386     }
387
388     /**
389      * This method is used to simulate event messages from DCAE that start the
390      * control loop (onset message).
391      * 
392      * @param policy
393      *            the controlLoopName comes from the policy
394      * @param requestId
395      *            the requestId for this event
396      * @param status
397      *            could be onset
398      */
399     protected void sendEvent(ControlLoopPolicy policy, UUID requestId, ControlLoopEventStatus status,
400             boolean isEnriched) {
401         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
402         event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName());
403         event.setRequestId(requestId);
404         event.setTarget("generic-vnf.vnf-id");
405         event.setTargetType(ControlLoopTargetType.VNF);
406         event.setClosedLoopAlarmStart(Instant.now());
407         event.setAai(new HashMap<>());
408         if (isEnriched) {
409             event.getAai().put("generic-vnf.is-closed-loop-disabled", "false");
410             event.getAai().put("generic-vnf.prov-status", "ACTIVE");
411             event.getAai().put("generic-vnf.vnf-id", "notused");
412         } else {
413             event.getAai().put("generic-vnf.vnf-id", "getFail");
414         }
415         event.setClosedLoopEventStatus(status);
416         StringBuilder sb = new StringBuilder();
417         sb.append("{ \"Configurations\":[ { \"data\":{ \"FAPService\":"
418                 + " { \"alias\":\"Cell1\", \"X0005b9Lte\" : { \"PhyCellIdInUse\" :"
419                 + " \"35\", \"PnfName\" : \"cu1\" }, \"CellConfig\":{ \"LTE\":{ \"RAN\":"
420                 + "{ \"Common\":{ \"CellIdentity\":\"1\" } } } } } } } ] }");
421
422         event.setPayload(sb.toString());
423         logger.debug("\n============ Policy receiving ONSET event !!! ===========\n");
424         logger.debug("\n============ event ===========\n {}", event);
425         kieSession.insert(event);
426     }
427
428     /**
429      * This method will dump all the facts in the working memory.
430      * 
431      * @param kieSession
432      *            the session containing the facts
433      */
434     public void dumpFacts(KieSession kieSession) {
435         logger.debug("Fact Count: {}", kieSession.getFactCount());
436         for (FactHandle handle : kieSession.getFactHandles()) {
437             logger.debug("FACT: {}", handle);
438         }
439     }
440
441 }