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