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.List;
25 import java.util.Properties;
27 import org.onap.policy.common.capabilities.Startable;
28 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
29 import org.onap.policy.common.endpoints.http.server.impl.IndexedHttpServletServerFactory;
30 import org.onap.policy.common.im.IntegrityMonitor;
31 import org.onap.policy.common.im.IntegrityMonitorException;
32 import org.onap.policy.drools.utils.PropertyUtil;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
37 * This class extends 'IntegrityMonitor' for use in the 'Drools PDP' virtual machine. The included
38 * audits are 'Database' and 'Repository'.
40 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 = new AuditBase[] {DbAudit.getInstance(), RepositoryAudit.getInstance()};
53 private static Properties subsystemTestProperties = null;
55 private static final String PROPERTIES_NAME = "feature-state-management.properties";
58 * 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 'IntegrityMonitor'
63 * @throws IntegrityMonitorException (passed from superclass)
65 private DroolsPDPIntegrityMonitor(String resourceName, Properties consolidatedProperties)
66 throws IntegrityMonitorException {
67 super(resourceName, consolidatedProperties);
70 private static void missingProperty(String prop) throws IntegrityMonitorException {
71 String msg = "init: missing IntegrityMonitor property: ".concat(prop);
73 throw new IntegrityMonitorException(msg);
76 private static void logPropertyValue(String prop, String val) {
77 if (logger.isInfoEnabled()) {
78 String msg = "\n\n init: property: " + prop + " = " + val + "\n";
84 * Static initialization -- create Drools Integrity Monitor, and an HTTP server to handle REST
87 * @throws StateManagementPropertiesException
88 * @throws IntegrityMonitorException
90 public static DroolsPDPIntegrityMonitor init(String configDir) throws IntegrityMonitorException {
92 logger.info("init: Entering and invoking PropertyUtil.getProperties() on '{}'", configDir);
95 Properties stateManagementProperties = getProperties(configDir);
97 // fetch and verify definitions of some properties, adding defaults where
99 // (the 'IntegrityMonitor' constructor does some additional verification)
101 checkPropError(stateManagementProperties, StateManagementProperties.TEST_HOST);
102 checkPropError(stateManagementProperties, StateManagementProperties.TEST_PORT);
104 addDefaultPropError(stateManagementProperties, StateManagementProperties.TEST_SERVICES,
105 StateManagementProperties.TEST_SERVICES_DEFAULT);
107 addDefaultPropError(stateManagementProperties, StateManagementProperties.TEST_REST_CLASSES,
108 StateManagementProperties.TEST_REST_CLASSES_DEFAULT);
110 addDefaultPropWarn(stateManagementProperties, StateManagementProperties.TEST_MANAGED,
111 StateManagementProperties.TEST_MANAGED_DEFAULT);
113 addDefaultPropWarn(stateManagementProperties, StateManagementProperties.TEST_SWAGGER,
114 StateManagementProperties.TEST_SWAGGER_DEFAULT);
116 checkPropError(stateManagementProperties, StateManagementProperties.RESOURCE_NAME);
117 checkPropError(stateManagementProperties, StateManagementProperties.FP_MONITOR_INTERVAL);
118 checkPropError(stateManagementProperties, StateManagementProperties.FAILED_COUNTER_THRESHOLD);
119 checkPropError(stateManagementProperties, StateManagementProperties.TEST_TRANS_INTERVAL);
120 checkPropError(stateManagementProperties, StateManagementProperties.WRITE_FPC_INTERVAL);
121 checkPropError(stateManagementProperties, StateManagementProperties.SITE_NAME);
122 checkPropError(stateManagementProperties, StateManagementProperties.NODE_TYPE);
123 checkPropError(stateManagementProperties, StateManagementProperties.DEPENDENCY_GROUPS);
124 checkPropError(stateManagementProperties, StateManagementProperties.DB_DRIVER);
125 checkPropError(stateManagementProperties, StateManagementProperties.DB_URL);
126 checkPropError(stateManagementProperties, StateManagementProperties.DB_USER);
127 checkPropError(stateManagementProperties, StateManagementProperties.DB_PWD);
129 String testHost = stateManagementProperties.getProperty(StateManagementProperties.TEST_HOST);
130 String testPort = stateManagementProperties.getProperty(StateManagementProperties.TEST_PORT);
131 String resourceName = stateManagementProperties.getProperty(StateManagementProperties.RESOURCE_NAME);
133 subsystemTestProperties = stateManagementProperties;
135 // Now that we've validated the properties, create Drools Integrity Monitor
136 // with these properties.
137 im = makeMonitor(resourceName, stateManagementProperties);
138 logger.info("init: New DroolsPDPIntegrityMonitor instantiated, resourceName = ", resourceName);
140 // create http server
141 makeRestServer(testHost, testPort, stateManagementProperties);
142 logger.info("init: Exiting and returning DroolsPDPIntegrityMonitor");
148 * Makes an Integrity Monitor.
150 * @param resourceName unique name of this Integrity Monitor
151 * @param properties properties used to configure the Integrity Monitor
153 * @throws IntegrityMonitorException
155 private static DroolsPDPIntegrityMonitor makeMonitor(String resourceName, Properties properties)
156 throws IntegrityMonitorException {
159 return new DroolsPDPIntegrityMonitor(resourceName, properties);
161 } catch (Exception e) {
162 throw new IntegrityMonitorException(e);
167 * Makes a rest server for the Integrity Monitor.
169 * @param testHost host name
170 * @param testPort port
171 * @param properties properties used to configure the rest server
172 * @throws IntegrityMonitorException
174 private static void makeRestServer(String testHost, String testPort, Properties properties)
175 throws IntegrityMonitorException {
178 logger.info("init: Starting HTTP server, addr= {}", testHost + ":" + testPort);
180 IntegrityMonitorRestServer server = new IntegrityMonitorRestServer();
181 server.init(properties);
183 } catch (Exception e) {
184 logger.error("init: Caught Exception attempting to start server on testPort= {} message:", testPort, e);
185 throw new IntegrityMonitorException(e);
190 * Gets the properties from the property file.
192 * @param configDir directory containing the property file
193 * @return the properties
194 * @throws IntegrityMonitorException
196 private static Properties getProperties(String configDir) throws IntegrityMonitorException {
198 return PropertyUtil.getProperties(configDir + "/" + PROPERTIES_NAME);
200 } catch (IOException e) {
201 throw new IntegrityMonitorException(e);
206 * Checks that a property is defined.
208 * @param props set of properties
209 * @param name name of the property to check
210 * @throws IntegrityMonitorException
212 private static void checkPropError(Properties props, String name) throws IntegrityMonitorException {
213 String val = props.getProperty(name);
215 missingProperty(name);
218 logPropertyValue(name, val);
222 * Checks a property's value to verify that it matches the expected value. If the property is
223 * not defined, then it is added to the property set, with the expected value. Logs an error if
224 * the property is defined, but does not have the expected value.
226 * @param props set of properties
227 * @param name name of the property to check
228 * @param expected expected/default value
230 private static void addDefaultPropError(Properties props, String name, String expected) {
231 String val = props.getProperty(name);
233 props.setProperty(name, expected);
235 } else if (!val.equals(expected)) {
236 logger.error(INVALID_PROPERTY_VALUE, name, expected);
239 logPropertyValue(name, val);
243 * Checks a property's value to verify that it matches the expected value. If the property is
244 * not defined, then it is added to the property set, with the expected value. Logs a warning if
245 * the property is defined, but does not have the expected value.
247 * @param props set of properties
248 * @param name name of the property to check
249 * @param expected expected/default value
251 private static void addDefaultPropWarn(Properties props, String name, String dflt) {
252 String val = props.getProperty(name);
254 props.setProperty(name, dflt);
256 } else if (!val.equals(dflt)) {
257 logger.warn(INVALID_PROPERTY_VALUE, name, dflt);
260 logPropertyValue(name, val);
264 * Run tests (audits) unique to Drools PDP VM (Database + Repository)
267 public void subsystemTest() throws IntegrityMonitorException {
268 logger.info("DroolsPDPIntegrityMonitor.subsystemTest called");
270 // clear all responses (non-null values indicate an error)
271 for (AuditBase audit : audits) {
272 audit.setResponse(null);
275 // invoke all of the audits
276 for (AuditBase audit : audits) {
278 // invoke the audit (responses are stored within the audit object)
279 audit.invoke(subsystemTestProperties);
280 } catch (Exception e) {
281 logger.error("{} audit error", audit.getName(), e);
282 if (audit.getResponse() == null) {
283 // if there is no current response, use the exception message
284 audit.setResponse(e.getMessage());
289 // will contain list of subsystems where the audit failed
290 String responseMsg = "";
292 // Loop through all of the audits, and see which ones have failed.
293 // NOTE: response information is stored within the audit objects
294 // themselves -- only one can run at a time.
295 for (AuditBase audit : audits) {
296 String response = audit.getResponse();
297 if (response != null) {
298 // the audit has failed -- add subsystem and
299 // and 'responseValue' with the new information
300 responseMsg = responseMsg.concat("\n" + audit.getName() + ": " + response);
304 if (!responseMsg.isEmpty()) {
305 throw new IntegrityMonitorException(responseMsg);
309 /* ============================================================ */
312 * This is the base class for audits invoked in 'subsystemTest'
314 public abstract static class AuditBase {
316 protected String name;
318 // non-null indicates the error response
319 protected String response;
322 * Constructor - initialize the name, and clear the initial response
324 * @param name name of the audit
326 public AuditBase(String name) {
328 this.response = null;
332 * @return the name of this audit
334 public String getName() {
339 * @return the response String (non-null indicates the error message)
341 public String getResponse() {
346 * Set the response string to the specified value
348 * @param value the new value of the response string (null = no errors)
350 public void setResponse(String value) {
355 * Abstract method to invoke the audit
357 * @param persistenceProperties Used for DB access
358 * @throws Exception passed in by the audit
360 abstract void invoke(Properties persistenceProperties) throws Exception;
363 public static class IntegrityMonitorRestServer implements Startable {
364 protected volatile HttpServletServer server = null;
365 protected volatile Properties integrityMonitorRestServerProperties = null;
367 public void init(Properties props) {
368 this.integrityMonitorRestServerProperties = props;
373 public boolean start() {
375 List<HttpServletServer> servers =
376 IndexedHttpServletServerFactory.getInstance().build(integrityMonitorRestServerProperties);
378 if (!servers.isEmpty()) {
379 server = servers.get(0);
383 } catch (Exception e) {
384 logger.error("Exception building servers", e);
391 private void waitServerStart() {
393 server.waitedStart(5);
394 } catch (Exception e) {
395 logger.error("Exception waiting for servers to start: ", e);
400 public boolean stop() {
403 } catch (Exception e) {
404 logger.error("Exception during stop", e);
411 public void shutdown() {
416 public synchronized boolean isAlive() {
417 return this.integrityMonitorRestServerProperties != null;
421 public static DroolsPDPIntegrityMonitor getInstance() throws IntegrityMonitorException {
422 if (logger.isDebugEnabled()) {
423 logger.debug("getInstance() called");
426 String msg = "No DroolsPDPIntegrityMonitor instance exists."
427 + " Please use the method DroolsPDPIntegrityMonitor init(String configDir)";
428 throw new IntegrityMonitorException(msg);