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