3b7410faca48cfeecc5c09feba8bd7ace070ca52
[policy/drools-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * feature-state-management
4  * ================================================================================
5  * Copyright (C) 2017 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.statemanagement;
22
23 import java.net.InetSocketAddress;
24 import java.util.ArrayList;
25 import java.util.Properties;
26
27 import org.onap.policy.common.im.IntegrityMonitor;
28 import org.onap.policy.common.im.IntegrityMonitorException;
29 import org.onap.policy.drools.http.server.HttpServletServer;
30 import org.onap.policy.drools.properties.Startable;
31 import org.onap.policy.drools.utils.PropertyUtil;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * This class extends 'IntegrityMonitor' for use in the 'Drools PDP'
37  * virtual machine. The included audits are 'Database' and 'Repository'.
38  */
39 public class DroolsPDPIntegrityMonitor extends IntegrityMonitor
40 {
41         
42         // get an instance of logger 
43   private static final Logger  logger = LoggerFactory.getLogger(DroolsPDPIntegrityMonitor.class);       
44
45   // static global instance
46   static private DroolsPDPIntegrityMonitor im = null;
47
48   // list of audits to run
49   static private AuditBase[] audits =
50         new AuditBase[]{DbAudit.getInstance(), RepositoryAudit.getInstance()};
51   
52   static private Properties subsystemTestProperties = null;
53
54   static private final String PROPERTIES_NAME = "feature-state-management.properties";
55   /**
56    * Static initialization -- create Drools Integrity Monitor, and
57    * an HTTP server to handle REST 'test' requests
58    */
59   static public DroolsPDPIntegrityMonitor init(String configDir) throws Exception
60   {
61                   
62         logger.info("init: Entering and invoking PropertyUtil.getProperties() on '{}'", configDir);
63                 
64         // read in properties
65         Properties stateManagementProperties =
66           PropertyUtil.getProperties(configDir + "/" + PROPERTIES_NAME);
67         
68         subsystemTestProperties = stateManagementProperties;
69         
70                 // fetch and verify definitions of some properties
71         // (the 'IntegrityMonitor' constructor does some additional verification)
72         
73         String resourceName = stateManagementProperties.getProperty("resource.name");
74         String hostPort = stateManagementProperties.getProperty("hostPort");
75         String fpMonitorInterval = stateManagementProperties.getProperty("fp_monitor_interval");
76         String failedCounterThreshold = stateManagementProperties.getProperty("failed_counter_threshold");
77         String testTransInterval = stateManagementProperties.getProperty("test_trans_interval");
78         String writeFpcInterval = stateManagementProperties.getProperty("write_fpc_interval");
79         String siteName = stateManagementProperties.getProperty("site_name");
80         String nodeType = stateManagementProperties.getProperty("node_type");
81         String dependencyGroups = stateManagementProperties.getProperty("dependency_groups");
82         String javaxPersistenceJdbcDriver = stateManagementProperties.getProperty("javax.persistence.jdbc.driver");
83         String javaxPersistenceJdbcUrl = stateManagementProperties.getProperty("javax.persistence.jdbc.url");
84         String javaxPersistenceJdbcUser = stateManagementProperties.getProperty("javax.persistence.jdbc.user");
85         String javaxPersistenceJdbcPassword = stateManagementProperties.getProperty("javax.persistence.jdbc.password");
86         
87         if (resourceName == null)
88           {
89                 logger.error("init: Missing IntegrityMonitor property: 'resource.name'");
90                 throw new Exception
91                           ("Missing IntegrityMonitor property: 'resource.name'");
92           }
93         if (hostPort == null)
94           {
95                 logger.error("init: Missing IntegrityMonitor property: 'hostPort'");
96                 throw new Exception
97                           ("Missing IntegrityMonitor property: 'hostPort'");
98           }
99         if (fpMonitorInterval == null)
100           {
101                 logger.error("init: Missing IntegrityMonitor property: 'fp_monitor_interval'");
102                 throw new Exception
103                           ("Missing IntegrityMonitor property: 'fp_monitor_interval'");
104           }     
105         if (failedCounterThreshold == null)
106           {
107                 logger.error("init: Missing IntegrityMonitor property: 'failed_counter_threshold'");
108                 throw new Exception
109                           ("Missing IntegrityMonitor property: 'failed_counter_threshold'");
110           }     
111         if (testTransInterval == null)
112           {
113                 logger.error("init: Missing IntegrityMonitor property: 'test_trans_interval'");
114                 throw new Exception
115                           ("Missing IntegrityMonitor property: 'test_trans_interval'");
116           }     
117         if (writeFpcInterval == null)
118           {
119                 logger.error("init: Missing IntegrityMonitor property: 'write_fpc_interval'");
120                 throw new Exception
121                           ("Missing IntegrityMonitor property: 'write_fpc_interval'");
122           }     
123         if (siteName == null)
124           {
125                 logger.error("init: Missing IntegrityMonitor property: 'site_name'");
126                 throw new Exception
127                           ("Missing IntegrityMonitor property: 'site_name'");
128           }     
129         if (nodeType == null)
130           {
131                 logger.error("init: Missing IntegrityMonitor property: 'node_type'");
132                 throw new Exception
133                           ("Missing IntegrityMonitor property: 'node_type'");
134           }     
135         if (dependencyGroups == null)
136           {
137                 logger.error("init: Missing IntegrityMonitor property: 'dependency_groups'");
138                 throw new Exception
139                           ("Missing IntegrityMonitor property: 'dependency_groups'");
140           }     
141         if (javaxPersistenceJdbcDriver == null)
142           {
143                 logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for xacml DB'");
144                 throw new Exception
145                           ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.driver for xacml DB'");
146           }             
147         if (javaxPersistenceJdbcUrl == null)
148           {
149                 logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.url  for xacml DB'");
150                 throw(new Exception
151                           ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.url  for xacml DB'"));
152           }                     
153         if (javaxPersistenceJdbcUser == null)
154           {
155                 logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for xacml DB'");
156                 throw new Exception
157                           ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.user for xacml DB'");
158           }                     
159         if (javaxPersistenceJdbcPassword == null)
160           {
161                 logger.error("init: Missing IntegrityMonitor property: 'javax.persistence.jbdc.password for xacml DB'");
162                 throw new Exception
163                           ("Missing IntegrityMonitor property: 'javax.persistence.jbdc.password'  for xacml DB'");
164           }             
165
166         // Now that we've validated the properties, create Drools Integrity Monitor
167         // with these properties.
168         im = new DroolsPDPIntegrityMonitor(resourceName,
169                                 stateManagementProperties);
170         logger.info("init: New DroolsPDPIntegrityMonitor instantiated, hostPort= {}", hostPort);
171
172         // determine host and port for HTTP server
173         int index = hostPort.lastIndexOf(':');
174         InetSocketAddress addr;
175
176         if (index < 0)
177           {
178                 addr = new InetSocketAddress(Integer.valueOf(hostPort));
179           }
180         else
181           {
182                 addr = new InetSocketAddress
183                   (hostPort.substring(0, index),
184                    Integer.valueOf(hostPort.substring(index + 1)));
185           }
186
187         // create http server
188         try {
189                 logger.info("init: Starting HTTP server, addr= {}", addr);
190                 IntegrityMonitorRestServer server = new IntegrityMonitorRestServer();
191                 
192                 server.init(stateManagementProperties);
193
194                 System.out.println("init: Started server on hostPort=" + hostPort);
195         } catch (Exception e) {
196                 logger.error("init: Caught Exception attempting to start server on hostPort= {}, message = {}",
197                                                                 hostPort, e.getMessage());
198                 throw e;
199
200         }
201         
202         logger.info("init: Exiting and returning DroolsPDPIntegrityMonitor");
203         return im;
204   }
205
206   /**
207    * Constructor - pass arguments to superclass, but remember properties
208    * @param resourceName unique name of this Integrity Monitor
209    * @param url the JMX URL of the MBean server
210    * @param properties properties used locally, as well as by
211    *    'IntegrityMonitor'
212    * @throws Exception (passed from superclass)
213    */
214         private DroolsPDPIntegrityMonitor(String resourceName,
215                         Properties consolidatedProperties
216                         ) throws Exception {
217         super(resourceName, consolidatedProperties);
218   }
219
220   /**
221    * Run tests (audits) unique to Drools PDP VM (Database + Repository)
222    */
223   @Override
224         public void subsystemTest() throws IntegrityMonitorException
225   {
226         logger.info("DroolsPDPIntegrityMonitor.subsystemTest called");
227
228         // clear all responses (non-null values indicate an error)
229         for (AuditBase audit : audits)
230           {
231                 audit.setResponse(null);
232           }
233
234         // invoke all of the audits
235         for (AuditBase audit : audits)
236           {
237                 try
238                   {
239                         // invoke the audit (responses are stored within the audit object)
240                         audit.invoke(subsystemTestProperties);
241                   }
242                 catch (Exception e)
243                   {
244                         logger.error("{} audit error", audit.getName(), e);
245                         if (audit.getResponse() == null)
246                           {
247                                 // if there is no current response, use the exception message
248                                 audit.setResponse(e.getMessage());
249                           }
250                   }
251           }
252         
253           // will contain list of subsystems where the audit failed
254           String responseMsg = "";
255
256           // Loop through all of the audits, and see which ones have failed.
257           // NOTE: response information is stored within the audit objects
258           // themselves -- only one can run at a time.
259           for (AuditBase audit : audits)
260                 {
261                   String response = audit.getResponse();
262                   if (response != null)
263                         {
264                           // the audit has failed -- add subsystem and 
265                           // and 'responseValue' with the new information
266                           responseMsg = responseMsg.concat("\n" + audit.getName() + ": " + response);
267                         }
268                 }
269           
270           if(!responseMsg.isEmpty()){
271                   throw new IntegrityMonitorException(responseMsg);
272           }
273   }
274
275   /* ============================================================ */
276
277   /**
278    * This is the base class for audits invoked in 'subsystemTest'
279    */
280   static public abstract class AuditBase
281   {
282         // name of the audit
283         protected String name;
284
285         // non-null indicates the error response
286         protected String response;
287
288         /**
289          * Constructor - initialize the name, and clear the initial response
290          * @param name name of the audit
291          */
292         public AuditBase(String name)
293         {
294           this.name = name;
295           this.response = null;
296         }
297
298         /**
299          * @return the name of this audit
300          */
301         public String getName()
302         {
303           return name;
304         }
305
306         /**
307          * @return the response String (non-null indicates the error message)
308          */
309         public String getResponse()
310         {
311           return response;
312         }
313
314         /**
315          * Set the response string to the specified value
316          * @param value the new value of the response string (null = no errors)
317          */
318         public void setResponse(String value)
319         {
320           response = value;
321         }
322
323         /**
324          * Abstract method to invoke the audit
325          * @param persistenceProperties Used for DB access
326          * @throws Exception passed in by the audit
327          */
328         abstract void invoke(Properties persistenceProperties) throws Exception;
329   }
330   
331         public static class IntegrityMonitorRestServer implements Startable {
332                 protected volatile HttpServletServer server = null;
333                 protected volatile Properties integrityMonitorRestServerProperties = null;
334                 
335                 public void init(Properties props) {
336                         this.integrityMonitorRestServerProperties = props;
337                         this.start();
338                 }
339                 
340                 @Override
341                 public boolean start() throws IllegalStateException {
342                         try {
343                                 ArrayList<HttpServletServer> servers = HttpServletServer.factory.build(integrityMonitorRestServerProperties);
344                                 
345                                 if (!servers.isEmpty()) {
346                                         server = servers.get(0);
347                                         
348                                         try {
349                                                 server.waitedStart(5);
350                                         } catch (Exception e) {
351                                                 logger.error("Exception waiting for servers to start: ", e);
352                                         }
353                                 }
354                         } catch (Exception e) {
355                                 logger.error("Exception building servers", e);
356                                 return false;
357                         }
358                         
359                         return true;
360                 }
361
362                 @Override
363                 public boolean stop() throws IllegalStateException {
364                         try {
365                                 server.stop();
366                         } catch (Exception e) {
367                                 logger.error("Exception during stop", e);
368                         }
369                         
370                         return true;
371                 }
372
373                 @Override
374                 public void shutdown() throws IllegalStateException {
375                         this.stop();
376                 }
377                 
378                 @Override
379                 public synchronized boolean isAlive() {
380                         return this.integrityMonitorRestServerProperties != null;
381                 }
382         }
383
384         public static DroolsPDPIntegrityMonitor getInstance() throws Exception{
385                 if(logger.isDebugEnabled()){
386                         logger.debug("getInstance() called");
387                 }
388                 if (im == null) {
389                         String msg = "No DroolsPDPIntegrityMonitor instance exists."
390                                         + " Please use the method DroolsPDPIntegrityMonitor init(String configDir)";
391                         throw new Exception(msg);
392                 }else{
393                         return im;
394                 }
395         }
396 }