ea9418bf830b6a3c733388ae8f07c092088c1322
[policy/drools-pdp.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * feature-active-standby-management
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.drools.controller.test;
22
23 import static org.junit.Assert.assertTrue;
24
25 import java.io.File;
26 import java.io.FileInputStream;
27 import java.util.Date;
28 import java.util.Properties;
29 import java.util.function.Supplier;
30 import javax.persistence.EntityManager;
31 import javax.persistence.EntityManagerFactory;
32 import javax.persistence.EntityTransaction;
33 import javax.persistence.Persistence;
34 import org.apache.commons.lang3.time.DateUtils;
35 import org.junit.After;
36 import org.junit.AfterClass;
37 import org.junit.Before;
38 import org.junit.BeforeClass;
39 import org.junit.Test;
40 import org.onap.policy.common.im.StateManagement;
41 import org.onap.policy.drools.activestandby.ActiveStandbyFeatureAPI;
42 import org.onap.policy.drools.activestandby.ActiveStandbyProperties;
43 import org.onap.policy.drools.activestandby.DroolsPdpEntity;
44 import org.onap.policy.drools.activestandby.DroolsPdpImpl;
45 import org.onap.policy.drools.activestandby.DroolsPdpsConnector;
46 import org.onap.policy.drools.activestandby.DroolsPdpsElectionHandler;
47 import org.onap.policy.drools.activestandby.JpaDroolsPdpsConnector;
48 import org.onap.policy.drools.core.PolicySessionFeatureApi;
49 import org.onap.policy.drools.statemanagement.StateManagementFeatureAPI;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /*
54  * Testing the allSeemsWell interface to verify that it correctly affects the
55  * operational state.
56  */
57
58 public class AllSeemsWellTest {
59     private static final Logger  logger = LoggerFactory.getLogger(AllSeemsWellTest.class);
60     /*
61      * Currently, the DroolsPdpsElectionHandler.DesignationWaiter is invoked every 1 seconds, starting
62      * at the start of the next multiple of pdpUpdateInterval, but with a minimum of 5 sec cushion
63      * to ensure that we wait for the DesignationWaiter to do its job, before
64      * checking the results. Add a few seconds for safety
65      */
66
67     private static int SLEEP_TIME_SEC = 10;
68
69     /*
70      * DroolsPdpsElectionHandler runs every 1 seconds, so it takes 10 seconds for the
71      * checkWaitTimer() method to time out and call allSeemsWell which then requires
72      * the forward progress counter to go stale which should add an additional 5 sec.
73      */
74
75     private static int STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC = 15;
76
77     /*
78      * As soon as the election hander successfully runs, it will resume the forward progress.
79      * If the election handler runs ever 1 sec and test transaction is run every 1 sec and
80      * then fpc is written every 1 sec and then the fpc is checked every 2 sec, that could
81      * take a total of 5 sec to recognize the resumption of progress.  So, add 1 for safety.
82      */
83     private static int RESUMED_ELECTION_HANDLER_SLEEP_TIME_SEC = 6;
84
85     private static EntityManagerFactory emfx;
86     private static EntityManagerFactory emfd;
87     private static EntityManager emx;
88     private static EntityManager emd;
89     private static EntityTransaction et;
90
91     private final String configDir = "src/test/resources/asw";
92
93     /*
94      * See the IntegrityMonitor.getJmxUrl() method for the rationale behind this jmx related processing.
95      */
96
97     /**
98      * Setup the class.
99      *
100      * @throws Exception exception
101      */
102     @BeforeClass
103     public static void setUpClass() throws Exception {
104
105         String userDir = System.getProperty("user.dir");
106         logger.debug("setUpClass: userDir={}", userDir);
107         System.setProperty("com.sun.management.jmxremote.port", "9980");
108         System.setProperty("com.sun.management.jmxremote.authenticate","false");
109     }
110
111     @AfterClass
112     public static void tearDownClass() throws Exception {
113     }
114
115     /**
116      * Setup.
117      *
118      * @throws Exception exception
119      */
120     @Before
121     public void setUp() throws Exception {
122         //Create teh data access for xaml db
123         Properties stateManagementProperties = new Properties();
124         stateManagementProperties.load(new FileInputStream(new File(
125                 configDir + "/feature-state-management.properties")));
126
127         emfx = Persistence.createEntityManagerFactory("junitXacmlPU", stateManagementProperties);
128
129         // Create an entity manager to use the DB
130         emx = emfx.createEntityManager();
131
132         //Create the data access for drools db
133         Properties activeStandbyProperties = new Properties();
134         activeStandbyProperties.load(new FileInputStream(new File(
135                 configDir + "/feature-active-standby-management.properties")));
136
137         emfd = Persistence.createEntityManagerFactory("junitDroolsPU", activeStandbyProperties);
138
139         // Create an entity manager to use the DB
140         emd = emfd.createEntityManager();
141
142         DroolsPdpsElectionHandler.setIsUnitTesting(true);
143     }
144
145     @After
146     public void tearDown() throws Exception {
147
148     }
149
150     /**
151      * Clean the xacml database.
152      */
153     public void cleanXacmlDb() {
154         et = emx.getTransaction();
155
156         et.begin();
157         // Make sure we leave the DB clean
158         emx.createQuery("DELETE FROM StateManagementEntity").executeUpdate();
159         emx.createQuery("DELETE FROM ResourceRegistrationEntity").executeUpdate();
160         emx.createQuery("DELETE FROM ForwardProgressEntity").executeUpdate();
161         emx.flush();
162         et.commit();
163     }
164
165     /**
166      * Clean the drools database.
167      */
168     public void cleanDroolsDb() {
169         et = emd.getTransaction();
170
171         et.begin();
172         // Make sure we leave the DB clean
173         emd.createQuery("DELETE FROM DroolsPdpEntity").executeUpdate();
174         emd.flush();
175         et.commit();
176     }
177
178
179     // Tests hot standby when there is only one PDP.
180
181     //@Ignore
182     @Test
183     public void testAllSeemsWell() throws Exception {
184
185         logger.debug("\n\ntestAllSeemsWell: Entering\n\n");
186         cleanXacmlDb();
187         cleanDroolsDb();
188
189         logger.debug("testAllSeemsWell: Reading stateManagementProperties");
190         Properties stateManagementProperties = new Properties();
191         stateManagementProperties.load(new FileInputStream(new File(
192                 configDir + "/feature-state-management.properties")));
193
194         logger.debug("testAllSeemsWell: Creating emfXacml");
195         final EntityManagerFactory emfXacml = Persistence.createEntityManagerFactory(
196                 "junitXacmlPU", stateManagementProperties);
197
198         logger.debug("testAllSeemsWell: Reading activeStandbyProperties");
199         Properties activeStandbyProperties = new Properties();
200         activeStandbyProperties.load(new FileInputStream(new File(
201                 configDir + "/feature-active-standby-management.properties")));
202         final String thisPdpId = activeStandbyProperties
203                 .getProperty(ActiveStandbyProperties.NODE_NAME);
204
205         logger.debug("testAllSeemsWell: Creating emfDrools");
206         EntityManagerFactory emfDrools = Persistence.createEntityManagerFactory(
207                 "junitDroolsPU", activeStandbyProperties);
208
209         DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emfDrools);
210
211         logger.debug("testAllSeemsWell: Cleaning up tables");
212         conn.deleteAllPdps();
213
214         /*
215          * Insert this PDP as not designated.  Initial standby state will be
216          * either null or cold standby.   Demoting should transit state to
217          * hot standby.
218          */
219
220         logger.debug("testAllSeemsWell: Inserting PDP={} as not designated", thisPdpId);
221         Date yesterday = DateUtils.addDays(new Date(), -1);
222         DroolsPdpImpl pdp = new DroolsPdpImpl(thisPdpId, false, 4, yesterday);
223         conn.insertPdp(pdp);
224         DroolsPdpEntity droolsPdpEntity = conn.getPdp(thisPdpId);
225         logger.debug("testAllSeemsWell: After insertion, PDP={} has DESIGNATED={}",
226                 thisPdpId, droolsPdpEntity.isDesignated());
227         assertTrue(droolsPdpEntity.isDesignated() == false);
228
229         logger.debug("testAllSeemsWell: Instantiating stateManagement object");
230         StateManagement sm = new StateManagement(emfXacml, "dummy");
231         sm.deleteAllStateManagementEntities();
232
233
234         // Now we want to create a StateManagementFeature and initialize it.  It will be
235         // discovered by the ActiveStandbyFeature when the election handler initializes.
236
237         StateManagementFeatureAPI stateManagementFeatureApi = null;
238         for (StateManagementFeatureAPI feature : StateManagementFeatureAPI.impl.getList()) {
239             ((PolicySessionFeatureApi) feature).globalInit(null, configDir);
240             stateManagementFeatureApi = feature;
241             logger.debug("testAllSeemsWell stateManagementFeature.getResourceName(): {}",
242                 stateManagementFeatureApi.getResourceName());
243             break;
244         }
245         if (stateManagementFeatureApi == null) {
246             logger.error("testAllSeemsWell failed to initialize.  "
247                     + "Unable to get instance of StateManagementFeatureAPI "
248                     + "with resourceID: {}", thisPdpId);
249             logger.debug("testAllSeemsWell failed to initialize.  "
250                     + "Unable to get instance of StateManagementFeatureAPI "
251                     + "with resourceID: {}", thisPdpId);
252         }
253         final StateManagementFeatureAPI smf = stateManagementFeatureApi;
254
255         // Create an ActiveStandbyFeature and initialize it. It will discover the StateManagementFeature
256         // that has been created.
257         ActiveStandbyFeatureAPI activeStandbyFeature = null;
258         for (ActiveStandbyFeatureAPI feature : ActiveStandbyFeatureAPI.impl.getList()) {
259             ((PolicySessionFeatureApi) feature).globalInit(null, configDir);
260             activeStandbyFeature = feature;
261             logger.debug("testAllSeemsWell activeStandbyFeature.getResourceName(): {}",
262                     activeStandbyFeature.getResourceName());
263             break;
264         }
265         if (activeStandbyFeature == null) {
266             logger.error("testAllSeemsWell failed to initialize.  "
267                     + "Unable to get instance of ActiveStandbyFeatureAPI "
268                     + "with resourceID: {}", thisPdpId);
269             logger.debug("testAllSeemsWell failed to initialize.  "
270                     + "Unable to get instance of ActiveStandbyFeatureAPI "
271                     + "with resourceID: {}", thisPdpId);
272         }
273
274
275         logger.debug("testAllSeemsWell: Demoting PDP={}", thisPdpId);
276         // demoting should cause state to transit to hotstandby
277         smf.demote();
278
279
280         logger.debug("testAllSeemsWell: Sleeping {} s, to allow JpaDroolsPdpsConnector "
281             + "time to check droolspdpentity table", SLEEP_TIME_SEC);
282         waitForCondition(()-> conn.getPdp(thisPdpId).isDesignated(),  SLEEP_TIME_SEC);
283
284         // Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service.
285
286         droolsPdpEntity = conn.getPdp(thisPdpId);
287         logger.debug("testAllSeemsWell: After sm.demote() invoked, DESIGNATED= {} "
288                 + "for PDP= {}", droolsPdpEntity.isDesignated(), thisPdpId);
289         assertTrue(droolsPdpEntity.isDesignated() == true);
290         String standbyStatus = smf.getStandbyStatus(thisPdpId);
291         logger.debug("testAllSeemsWell: After demotion, PDP= {} "
292                 + "has standbyStatus= {}", thisPdpId, standbyStatus);
293         assertTrue(standbyStatus != null  &&  standbyStatus.equals(StateManagement.PROVIDING_SERVICE));
294
295         //Now we want to stall the election handler and see the if AllSeemsWell will make the
296         //standbystatus = coldstandby
297
298         DroolsPdpsElectionHandler.setIsStalled(true);
299
300         logger.debug("testAllSeemsWell: Sleeping {} s, to allow checkWaitTimer to recognize "
301                 + "the election handler has stalled and for the testTransaction to fail to "
302                 + "increment forward progress and for the lack of forward progress to be recognized.",
303             STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC);
304
305
306         //It takes 10x the update interval (1 sec) before the watcher will declare the election handler dead
307         //and that just stops forward progress counter.  So, the fp monitor must then run to determine
308         //if the fpc has stalled.  That will take about another 5 sec.
309         waitForCondition(()-> smf.getStandbyStatus().equals(StateManagement.COLD_STANDBY),
310             STALLED_ELECTION_HANDLER_SLEEP_TIME_SEC);
311
312         logger.debug("testAllSeemsWell: After isStalled=true, PDP= {} "
313                 + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId));
314
315         assertTrue(smf.getStandbyStatus().equals(StateManagement.COLD_STANDBY));
316
317         //Now lets resume the election handler
318         DroolsPdpsElectionHandler.setIsStalled(false);
319
320         waitForCondition(() -> smf.getStandbyStatus().equals(StateManagement.PROVIDING_SERVICE),
321             RESUMED_ELECTION_HANDLER_SLEEP_TIME_SEC);
322
323         logger.debug("testAllSeemsWell: After isStalled=false, PDP= {} "
324                 + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId));
325
326         assertTrue(smf.getStandbyStatus().equals(StateManagement.PROVIDING_SERVICE));
327
328         //resumedElectionHandlerSleepTime = 5000;
329         logger.debug("\n\ntestAllSeemsWell: Exiting\n\n");
330
331     }
332
333     private void waitForCondition(Supplier<Boolean> testCondition, int timeoutInSeconds) throws InterruptedException {
334         int maxIterations = timeoutInSeconds * 10;
335         int iterations = 0;
336         while (!testCondition.get() && iterations < maxIterations) {
337             iterations++;
338             Thread.sleep(100);
339         }
340     }
341 }