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