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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.onap.policy.drools.statemanagement;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.Properties;
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;
36 * This class extends 'IntegrityMonitor' for use in the 'Drools PDP'
37 * virtual machine. The included audits are 'Database' and 'Repository'.
39 public class DroolsPDPIntegrityMonitor extends IntegrityMonitor
42 private static final String INVALID_PROPERTY_VALUE = "init: property {} does not have the expected value of {}";
44 // get an instance of logger
45 private static final Logger logger = LoggerFactory.getLogger(DroolsPDPIntegrityMonitor.class);
47 // static global instance
48 private static DroolsPDPIntegrityMonitor im = null;
50 // list of audits to run
51 private static AuditBase[] audits =
52 new AuditBase[]{DbAudit.getInstance(), RepositoryAudit.getInstance()};
54 private static Properties subsystemTestProperties = null;
56 private static final String PROPERTIES_NAME = "feature-state-management.properties";
59 * Constructor - pass arguments to superclass, but remember properties
60 * @param resourceName unique name of this Integrity Monitor
61 * @param url the JMX URL of the MBean server
62 * @param properties properties used locally, as well as by
64 * @throws IntegrityMonitorException (passed from superclass)
66 private DroolsPDPIntegrityMonitor(String resourceName,
67 Properties consolidatedProperties
68 ) throws IntegrityMonitorException {
69 super(resourceName, consolidatedProperties);
72 private static void missingProperty(String prop) throws IntegrityMonitorException{
73 String msg = "init: missing IntegrityMonitor property: ".concat(prop);
75 throw new IntegrityMonitorException(msg);
78 private static void logPropertyValue(String prop, String val){
79 if(logger.isInfoEnabled()){
80 String msg = "\n\n init: property: " + prop + " = " + val + "\n";
86 * Static initialization -- create Drools Integrity Monitor, and
87 * an HTTP server to handle REST 'test' requests
88 * @throws StateManagementPropertiesException
89 * @throws IntegrityMonitorException
91 public static DroolsPDPIntegrityMonitor init(String configDir) throws IntegrityMonitorException
94 logger.info("init: Entering and invoking PropertyUtil.getProperties() on '{}'", configDir);
97 Properties stateManagementProperties = getProperties(configDir);
99 // fetch and verify definitions of some properties, adding defaults where
101 // (the 'IntegrityMonitor' constructor does some additional verification)
103 checkPropError(stateManagementProperties, StateManagementProperties.TEST_HOST);
104 checkPropError(stateManagementProperties, StateManagementProperties.TEST_PORT);
106 addDefaultPropError(stateManagementProperties,
107 StateManagementProperties.TEST_SERVICES,
108 StateManagementProperties.TEST_SERVICES_DEFAULT);
110 addDefaultPropError(stateManagementProperties,
111 StateManagementProperties.TEST_REST_CLASSES,
112 StateManagementProperties.TEST_REST_CLASSES_DEFAULT);
114 addDefaultPropWarn(stateManagementProperties,
115 StateManagementProperties.TEST_MANAGED,
116 StateManagementProperties.TEST_MANAGED_DEFAULT);
118 addDefaultPropWarn(stateManagementProperties,
119 StateManagementProperties.TEST_SWAGGER,
120 StateManagementProperties.TEST_SWAGGER_DEFAULT);
122 checkPropError(stateManagementProperties, StateManagementProperties.RESOURCE_NAME);
123 checkPropError(stateManagementProperties, StateManagementProperties.FP_MONITOR_INTERVAL);
124 checkPropError(stateManagementProperties, StateManagementProperties.FAILED_COUNTER_THRESHOLD);
125 checkPropError(stateManagementProperties, StateManagementProperties.TEST_TRANS_INTERVAL);
126 checkPropError(stateManagementProperties, StateManagementProperties.WRITE_FPC_INTERVAL);
127 checkPropError(stateManagementProperties, StateManagementProperties.SITE_NAME);
128 checkPropError(stateManagementProperties, StateManagementProperties.NODE_TYPE);
129 checkPropError(stateManagementProperties, StateManagementProperties.DEPENDENCY_GROUPS);
130 checkPropError(stateManagementProperties, StateManagementProperties.DB_DRIVER);
131 checkPropError(stateManagementProperties, StateManagementProperties.DB_URL);
132 checkPropError(stateManagementProperties, StateManagementProperties.DB_USER);
133 checkPropError(stateManagementProperties, StateManagementProperties.DB_PWD);
135 String testHost = stateManagementProperties.getProperty(StateManagementProperties.TEST_HOST);
136 String testPort = stateManagementProperties.getProperty(StateManagementProperties.TEST_PORT);
137 String resourceName = stateManagementProperties.getProperty(StateManagementProperties.RESOURCE_NAME);
139 subsystemTestProperties = stateManagementProperties;
141 // Now that we've validated the properties, create Drools Integrity Monitor
142 // with these properties.
143 im = makeMonitor(resourceName, stateManagementProperties);
144 logger.info("init: New DroolsPDPIntegrityMonitor instantiated, resourceName = ", resourceName);
146 // create http server
147 makeRestServer(testHost, testPort, stateManagementProperties);
148 logger.info("init: Exiting and returning DroolsPDPIntegrityMonitor");
154 * Makes an Integrity Monitor.
155 * @param resourceName unique name of this Integrity Monitor
156 * @param properties properties used to configure the Integrity Monitor
158 * @throws IntegrityMonitorException
160 private static DroolsPDPIntegrityMonitor makeMonitor(String resourceName, Properties properties)
161 throws IntegrityMonitorException {
164 return new DroolsPDPIntegrityMonitor(resourceName, properties);
166 } catch (Exception e) {
167 throw new IntegrityMonitorException(e);
172 * Makes a rest server for the Integrity Monitor.
173 * @param testHost host name
174 * @param testPort port
175 * @param properties properties used to configure the rest server
176 * @throws IntegrityMonitorException
178 private static void makeRestServer(String testHost, String testPort, Properties properties)
179 throws IntegrityMonitorException {
182 logger.info("init: Starting HTTP server, addr= {}", testHost+":"+testPort);
184 IntegrityMonitorRestServer server = new IntegrityMonitorRestServer();
185 server.init(properties);
187 } catch (Exception e) {
188 logger.error("init: Caught Exception attempting to start server on testPort= {} message:",
190 throw new IntegrityMonitorException(e);
195 * Gets the properties from the property file.
196 * @param configDir directory containing the property file
197 * @return the properties
198 * @throws IntegrityMonitorException
200 private static Properties getProperties(String configDir) throws IntegrityMonitorException {
202 return PropertyUtil.getProperties(configDir + "/" + PROPERTIES_NAME);
204 } catch (IOException e) {
205 throw new IntegrityMonitorException(e);
210 * Checks that a property is defined.
211 * @param props set of properties
212 * @param name name of the property to check
213 * @throws IntegrityMonitorException
215 private static void checkPropError(Properties props, String name) throws IntegrityMonitorException {
216 String val = props.getProperty(name);
218 missingProperty(name);
221 logPropertyValue(name, val);
225 * Checks a property's value to verify that it matches the expected value.
226 * If the property is not defined, then it is added to the property set,
227 * with the expected value. Logs an error if the property is defined,
228 * but does not have the expected value.
229 * @param props set of properties
230 * @param name name of the property to check
231 * @param expected expected/default value
233 private static void addDefaultPropError(Properties props, String name, String expected) {
234 String val = props.getProperty(name);
236 props.setProperty(name, expected);
238 } else if( ! val.equals(expected)) {
239 logger.error(INVALID_PROPERTY_VALUE, name, expected);
242 logPropertyValue(name, val);
246 * Checks a property's value to verify that it matches the expected value.
247 * If the property is not defined, then it is added to the property set,
248 * with the expected value. Logs a warning if the property is defined,
249 * but does not have the expected value.
250 * @param props set of properties
251 * @param name name of the property to check
252 * @param expected expected/default value
254 private static void addDefaultPropWarn(Properties props, String name, String dflt) {
255 String val = props.getProperty(name);
257 props.setProperty(name, dflt);
259 } else if( ! val.equals(dflt)) {
260 logger.warn(INVALID_PROPERTY_VALUE, name, dflt);
263 logPropertyValue(name, val);
267 * Run tests (audits) unique to Drools PDP VM (Database + Repository)
270 public void subsystemTest() throws IntegrityMonitorException
272 logger.info("DroolsPDPIntegrityMonitor.subsystemTest called");
274 // clear all responses (non-null values indicate an error)
275 for (AuditBase audit : audits)
277 audit.setResponse(null);
280 // invoke all of the audits
281 for (AuditBase audit : audits)
285 // invoke the audit (responses are stored within the audit object)
286 audit.invoke(subsystemTestProperties);
290 logger.error("{} audit error", audit.getName(), e);
291 if (audit.getResponse() == null)
293 // if there is no current response, use the exception message
294 audit.setResponse(e.getMessage());
299 // will contain list of subsystems where the audit failed
300 String responseMsg = "";
302 // Loop through all of the audits, and see which ones have failed.
303 // NOTE: response information is stored within the audit objects
304 // themselves -- only one can run at a time.
305 for (AuditBase audit : audits)
307 String response = audit.getResponse();
308 if (response != null)
310 // the audit has failed -- add subsystem and
311 // and 'responseValue' with the new information
312 responseMsg = responseMsg.concat("\n" + audit.getName() + ": " + response);
316 if(!responseMsg.isEmpty()){
317 throw new IntegrityMonitorException(responseMsg);
321 /* ============================================================ */
324 * This is the base class for audits invoked in 'subsystemTest'
326 public abstract static class AuditBase
329 protected String name;
331 // non-null indicates the error response
332 protected String response;
335 * Constructor - initialize the name, and clear the initial response
336 * @param name name of the audit
338 public AuditBase(String name)
341 this.response = null;
345 * @return the name of this audit
347 public String getName()
353 * @return the response String (non-null indicates the error message)
355 public String getResponse()
361 * Set the response string to the specified value
362 * @param value the new value of the response string (null = no errors)
364 public void setResponse(String value)
370 * Abstract method to invoke the audit
371 * @param persistenceProperties Used for DB access
372 * @throws Exception passed in by the audit
374 abstract void invoke(Properties persistenceProperties) throws Exception;
377 public static class IntegrityMonitorRestServer implements Startable {
378 protected volatile HttpServletServer server = null;
379 protected volatile Properties integrityMonitorRestServerProperties = null;
381 public void init(Properties props) {
382 this.integrityMonitorRestServerProperties = props;
387 public boolean start() {
389 List<HttpServletServer> servers = HttpServletServer.factory.build(integrityMonitorRestServerProperties);
391 if (!servers.isEmpty()) {
392 server = servers.get(0);
396 } catch (Exception e) {
397 logger.error("Exception building servers", e);
404 private void waitServerStart() {
406 server.waitedStart(5);
407 } catch (Exception e) {
408 logger.error("Exception waiting for servers to start: ", e);
413 public boolean stop() {
416 } catch (Exception e) {
417 logger.error("Exception during stop", e);
424 public void shutdown() {
429 public synchronized boolean isAlive() {
430 return this.integrityMonitorRestServerProperties != null;
434 public static DroolsPDPIntegrityMonitor getInstance() throws IntegrityMonitorException{
435 if(logger.isDebugEnabled()){
436 logger.debug("getInstance() called");
439 String msg = "No DroolsPDPIntegrityMonitor instance exists."
440 + " Please use the method DroolsPDPIntegrityMonitor init(String configDir)";
441 throw new IntegrityMonitorException(msg);