2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017-2021 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;
28 import org.onap.policy.common.capabilities.Startable;
29 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
30 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
31 import org.onap.policy.common.im.IntegrityMonitor;
32 import org.onap.policy.common.im.IntegrityMonitorException;
33 import org.onap.policy.drools.utils.PropertyUtil;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 * This class extends 'IntegrityMonitor' for use in the 'Drools PDP' virtual machine. The included
39 * audits are 'Database' and 'Repository'.
41 public class DroolsPdpIntegrityMonitor extends IntegrityMonitor {
43 private static final String INVALID_PROPERTY_VALUE = "init: property {} does not have the expected value of {}";
45 // get an instance of logger
46 private static final Logger logger = LoggerFactory.getLogger(DroolsPdpIntegrityMonitor.class);
48 // static global instance
49 private static DroolsPdpIntegrityMonitor im = null;
51 // list of audits to run
52 private static final AuditBase[] audits = 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.
61 * @param resourceName unique name of this Integrity Monitor
62 * @param consolidatedProperties 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 logger.info("\n\n init: property: {} = {}\n", prop, val);
81 * Static initialization -- create Drools Integrity Monitor, and an HTTP server to handle REST
84 * @throws IntegrityMonitorException exception
86 public static DroolsPdpIntegrityMonitor init(String configDir) throws IntegrityMonitorException {
88 logger.info("init: Entering and invoking PropertyUtil.getProperties() on '{}'", configDir);
91 var stateManagementProperties = getProperties(configDir);
93 // fetch and verify definitions of some properties, adding defaults where
95 // (the 'IntegrityMonitor' constructor does some additional verification)
97 checkPropError(stateManagementProperties, StateManagementProperties.TEST_HOST);
98 checkPropError(stateManagementProperties, StateManagementProperties.TEST_PORT);
100 addDefaultPropError(stateManagementProperties, StateManagementProperties.TEST_SERVICES,
101 StateManagementProperties.TEST_SERVICES_DEFAULT);
103 addDefaultPropError(stateManagementProperties, StateManagementProperties.TEST_REST_CLASSES,
104 StateManagementProperties.TEST_REST_CLASSES_DEFAULT);
106 addDefaultPropWarn(stateManagementProperties, StateManagementProperties.TEST_MANAGED,
107 StateManagementProperties.TEST_MANAGED_DEFAULT);
109 addDefaultPropWarn(stateManagementProperties, StateManagementProperties.TEST_SWAGGER,
110 StateManagementProperties.TEST_SWAGGER_DEFAULT);
112 checkPropError(stateManagementProperties, StateManagementProperties.RESOURCE_NAME);
113 checkPropError(stateManagementProperties, StateManagementProperties.FP_MONITOR_INTERVAL);
114 checkPropError(stateManagementProperties, StateManagementProperties.FAILED_COUNTER_THRESHOLD);
115 checkPropError(stateManagementProperties, StateManagementProperties.TEST_TRANS_INTERVAL);
116 checkPropError(stateManagementProperties, StateManagementProperties.WRITE_FPC_INTERVAL);
117 checkPropError(stateManagementProperties, StateManagementProperties.SITE_NAME);
118 checkPropError(stateManagementProperties, StateManagementProperties.NODE_TYPE);
119 checkPropError(stateManagementProperties, StateManagementProperties.DEPENDENCY_GROUPS);
120 checkPropError(stateManagementProperties, StateManagementProperties.DB_TYPE);
121 checkPropError(stateManagementProperties, StateManagementProperties.DB_DRIVER);
122 checkPropError(stateManagementProperties, StateManagementProperties.DB_URL);
123 checkPropError(stateManagementProperties, StateManagementProperties.DB_USER);
124 checkPropError(stateManagementProperties, StateManagementProperties.DB_PWD);
126 final String testHost = stateManagementProperties.getProperty(StateManagementProperties.TEST_HOST);
127 final String testPort = stateManagementProperties.getProperty(StateManagementProperties.TEST_PORT);
128 final String resourceName = stateManagementProperties.getProperty(StateManagementProperties.RESOURCE_NAME);
130 subsystemTestProperties = stateManagementProperties;
132 // Now that we've validated the properties, create Drools Integrity Monitor
133 // with these properties.
134 im = makeMonitor(resourceName, stateManagementProperties);
135 logger.info("init: New DroolsPDPIntegrityMonitor instantiated, resourceName = {}", resourceName);
137 // create http server
138 makeRestServer(testHost, testPort, stateManagementProperties);
139 logger.info("init: Exiting and returning DroolsPDPIntegrityMonitor");
145 * Makes an Integrity Monitor.
147 * @param resourceName unique name of this Integrity Monitor
148 * @param properties properties used to configure the Integrity Monitor
149 * @return monitor object
150 * @throws IntegrityMonitorException exception
152 private static DroolsPdpIntegrityMonitor makeMonitor(String resourceName, Properties properties)
153 throws IntegrityMonitorException {
156 return new DroolsPdpIntegrityMonitor(resourceName, properties);
158 } catch (Exception e) {
159 throw new IntegrityMonitorException(e);
164 * Makes a rest server for the Integrity Monitor.
166 * @param testHost host name
167 * @param testPort port
168 * @param properties properties used to configure the rest server
169 * @throws IntegrityMonitorException exception
171 private static void makeRestServer(String testHost, String testPort, Properties properties)
172 throws IntegrityMonitorException {
175 logger.info("init: Starting HTTP server, addr= {}:{}", testHost, testPort);
177 new IntegrityMonitorRestServer(properties);
179 } catch (Exception e) {
180 logger.error("init: Caught Exception attempting to start server on testPort={}", testPort);
181 throw new IntegrityMonitorException(e);
186 * Gets the properties from the property file.
188 * @param configDir directory containing the property file
189 * @return the properties
190 * @throws IntegrityMonitorException exception
192 private static Properties getProperties(String configDir) throws IntegrityMonitorException {
194 return PropertyUtil.getProperties(configDir + "/" + PROPERTIES_NAME);
196 } catch (IOException e) {
197 throw new IntegrityMonitorException(e);
202 * Checks that a property is defined.
204 * @param props set of properties
205 * @param name name of the property to check
206 * @throws IntegrityMonitorException exception
208 private static void checkPropError(Properties props, String name) throws IntegrityMonitorException {
209 String val = props.getProperty(name);
211 missingProperty(name);
214 logPropertyValue(name, val);
218 * Checks a property's value to verify that it matches the expected value. If the property is
219 * not defined, then it is added to the property set, with the expected value. Logs an error if
220 * the property is defined, but does not have the expected value.
222 * @param props set of properties
223 * @param name name of the property to check
224 * @param expected expected/default value
226 private static void addDefaultPropError(Properties props, String name, String expected) {
227 String val = props.getProperty(name);
229 props.setProperty(name, expected);
231 } else if (!val.equals(expected)) {
232 logger.error(INVALID_PROPERTY_VALUE, name, expected);
235 logPropertyValue(name, val);
239 * Checks a property's value to verify that it matches the expected value. If the property is
240 * not defined, then it is added to the property set, with the expected value. Logs a warning if
241 * the property is defined, but does not have the expected value.
243 * @param props set of properties
244 * @param name name of the property to check
245 * @param dflt expected/default value
247 private static void addDefaultPropWarn(Properties props, String name, String dflt) {
248 String val = props.getProperty(name);
250 props.setProperty(name, dflt);
252 } else if (!val.equals(dflt)) {
253 logger.warn(INVALID_PROPERTY_VALUE, name, dflt);
256 logPropertyValue(name, val);
260 * Run tests (audits) unique to Drools PDP VM (Database + Repository).
263 public void subsystemTest() throws IntegrityMonitorException {
264 logger.info("DroolsPDPIntegrityMonitor.subsystemTest called");
266 // clear all responses (non-null values indicate an error)
267 for (AuditBase audit : audits) {
268 audit.setResponse(null);
271 // invoke all of the audits
272 for (AuditBase audit : audits) {
274 // invoke the audit (responses are stored within the audit object)
275 audit.invoke(subsystemTestProperties);
276 } catch (Exception e) {
277 logger.error("{} audit error", audit.getName(), e);
278 if (audit.getResponse() == null) {
279 // if there is no current response, use the exception message
280 audit.setResponse(e.getMessage());
285 // will contain list of subsystems where the audit failed
286 var responseMsg = "";
288 // Loop through all of the audits, and see which ones have failed.
289 // NOTE: response information is stored within the audit objects
290 // themselves -- only one can run at a time.
291 for (AuditBase audit : audits) {
292 String response = audit.getResponse();
293 if (response != null) {
294 // the audit has failed -- add subsystem and
295 // and 'responseValue' with the new information
296 responseMsg = responseMsg.concat("\n" + audit.getName() + ": " + response);
300 if (!responseMsg.isEmpty()) {
301 throw new IntegrityMonitorException(responseMsg);
305 /* ============================================================ */
308 * This is the base class for audits invoked in 'subsystemTest'.
311 public abstract static class AuditBase {
313 protected String name;
315 // non-null indicates the error response
317 protected String response;
320 * Constructor - initialize the name, and clear the initial response.
322 * @param name name of the audit
324 protected AuditBase(String name) {
326 this.response = null;
330 * Abstract method to invoke the audit.
332 * @param persistenceProperties Used for DB access
333 * @throws IntegrityMonitorException passed in by the audit
335 abstract void invoke(Properties persistenceProperties) throws IntegrityMonitorException;
338 public static class IntegrityMonitorRestServer implements Startable {
339 protected HttpServletServer server = null;
340 protected final Properties integrityMonitorRestServerProperties;
342 public IntegrityMonitorRestServer(Properties props) {
343 this.integrityMonitorRestServerProperties = props;
348 public boolean start() {
350 List<HttpServletServer> servers = HttpServletServerFactoryInstance.getServerFactory()
351 .build(integrityMonitorRestServerProperties);
353 if (!servers.isEmpty()) {
354 server = servers.get(0);
358 } catch (Exception e) {
359 logger.error("Exception building servers", e);
366 private void waitServerStart() {
368 server.waitedStart(5);
369 } catch (Exception e) {
370 logger.error("Exception waiting for servers to start: ", e);
371 Thread.currentThread().interrupt();
376 public boolean stop() {
379 } catch (Exception e) {
380 logger.error("Exception during stop", e);
387 public void shutdown() {
392 public synchronized boolean isAlive() {
393 return this.integrityMonitorRestServerProperties != null;
398 * Returns the instance.
400 * @return DroolsPDPIntegrityMonitor object
401 * @throws IntegrityMonitorException exception
403 public static DroolsPdpIntegrityMonitor getInstance() throws IntegrityMonitorException {
404 logger.debug("getInstance() called");
406 String msg = "No DroolsPDPIntegrityMonitor instance exists."
407 + " Please use the method DroolsPDPIntegrityMonitor init(String configDir)";
408 throw new IntegrityMonitorException(msg);