summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Mizyn <d.mizyn@samsung.com>2020-03-05 14:14:04 +0100
committerDominik Mizyn <d.mizyn@partner.samsung.com>2020-10-05 10:34:48 +0200
commitb5cf61b0a4b1335a96a785674ca3d4e844d212ef (patch)
treebf855860e555a4304fd9150ba176556987c526ff
parentbf2a03463f57d9b18ce96467b3b8d7f3b1ae1025 (diff)
HealthCheckController up
HealthCheckController up and all needed services Issue-ID: PORTAL-710 Change-Id: I54cc4c32ea03b773833bab4296dcc0d67d3f2ea2 Signed-off-by: Dominik Mizyn <d.mizyn@samsung.com>
-rw-r--r--portal-BE/Dockerfile4
-rw-r--r--portal-BE/docker-compose.yml2
-rw-r--r--portal-BE/pom.xml37
-rw-r--r--portal-BE/src/main/java/org/onap/portal/controller/HealthCheckController.java237
-rw-r--r--portal-BE/src/main/java/org/onap/portal/controller/ManifestController.java81
-rw-r--r--portal-BE/src/main/java/org/onap/portal/scheduler/healthMonitor/HealthMonitor.java359
-rw-r--r--portal-BE/src/main/java/org/onap/portal/service/ManifestService.java35
-rw-r--r--portal-BE/src/main/resources/application.properties2
8 files changed, 729 insertions, 28 deletions
diff --git a/portal-BE/Dockerfile b/portal-BE/Dockerfile
index 99275dca..3da3eec2 100644
--- a/portal-BE/Dockerfile
+++ b/portal-BE/Dockerfile
@@ -1,6 +1,6 @@
FROM openjdk:8-jdk-alpine
VOLUME /tmp
-EXPOSE 8080
+EXPOSE 8081
ARG DEPENDENCY=target
ADD ${DEPENDENCY}/portal-0.0.1-SNAPSHOT.jar portal-0.0.1-SNAPSHOT.jar
-ENTRYPOINT ["java","-jar","portal-0.0.1-SNAPSHOT.jar"] \ No newline at end of file
+ENTRYPOINT ["java","-jar","portal-0.0.1-SNAPSHOT.jar"]
diff --git a/portal-BE/docker-compose.yml b/portal-BE/docker-compose.yml
index 9b8f1ed0..096695a4 100644
--- a/portal-BE/docker-compose.yml
+++ b/portal-BE/docker-compose.yml
@@ -32,7 +32,7 @@ services:
container_name: portal_APP
restart: always
ports:
- - 8080:8080
+ - 8081:8081
environment:
- spring.datasource.username=${spring_datasource_username}
- spring.datasource.password=${spring_datasource_password}
diff --git a/portal-BE/pom.xml b/portal-BE/pom.xml
index f7f9c371..266c05e7 100644
--- a/portal-BE/pom.xml
+++ b/portal-BE/pom.xml
@@ -152,6 +152,13 @@
<version>6.0.18.Final</version>
<scope>compile</scope>
</dependency>
+ <!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
+ <dependency>
+ <groupId>com.zaxxer</groupId>
+ <artifactId>HikariCP</artifactId>
+ <version>3.4.5</version>
+ </dependency>
+
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
@@ -182,12 +189,13 @@
<version>2.6.0</version>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.onap.portal.sdk</groupId>
+ <artifactId>epsdk-music</artifactId>
+ <version>2.6.0</version>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
- <properties>
- <docker.image.prefix>portal</docker.image.prefix>
- <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml,${project.reporting.outputDirectory}/jacoco-it/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
- <sonar.skip>true</sonar.skip>
- </properties>
<build>
<plugins>
<plugin>
@@ -240,25 +248,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <groupId>org.jacoco</groupId>
- <artifactId>jacoco-maven-plugin</artifactId>
- <version>0.7.7.201606060606</version>
- <executions>
- <execution>
- <goals>
- <goal>prepare-agent</goal>
- </goals>
- </execution>
- <execution>
- <id>report</id>
- <phase>prepare-package</phase>
- <goals>
- <goal>report</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
<resources>
<resource>
diff --git a/portal-BE/src/main/java/org/onap/portal/controller/HealthCheckController.java b/portal-BE/src/main/java/org/onap/portal/controller/HealthCheckController.java
new file mode 100644
index 00000000..ec2f9145
--- /dev/null
+++ b/portal-BE/src/main/java/org/onap/portal/controller/HealthCheckController.java
@@ -0,0 +1,237 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+package org.onap.portal.controller;
+
+import com.google.gson.Gson;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.onap.music.main.MusicUtil;
+import org.onap.portal.logging.format.EPAppMessagesEnum;
+import org.onap.portal.logging.logic.EPLogUtil;
+import org.onap.portal.scheduler.healthMonitor.HealthMonitor;
+import org.onap.portal.utils.EPCommonSystemProperties;
+import org.onap.portal.utils.EcompPortalUtils;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.slf4j.MDC;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@Configuration
+@EnableAspectJAutoProxy
+public class HealthCheckController {
+
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HealthCheckController.class);
+
+ private class HealthStatus {
+
+ public int statusCode;
+ @SuppressWarnings("unused")
+ public String body;
+
+ public HealthStatus(int code, String body) {
+ this.statusCode = code;
+ this.body = body;
+ }
+ }
+
+ private class HealthStatusInfo {
+
+ HealthStatusInfo(String healthCheckComponent) {
+ this.healthCheckComponent = healthCheckComponent;
+ this.healthCheckStatus = statusUp; // Default value
+ this.version = "";
+ this.description = statusOk; // Default value
+ this.hostName = "";
+ this.ipAddress = "";
+ this.dbClusterStatus = "";
+ this.dbPermissions = "";
+ }
+
+ @SuppressWarnings("unused")
+ public String healthCheckComponent;
+ @SuppressWarnings("unused")
+ public String healthCheckStatus;
+ @SuppressWarnings("unused")
+ public String version;
+ @SuppressWarnings("unused")
+ public String description;
+ @SuppressWarnings("unused")
+ public String hostName;
+ @SuppressWarnings("unused")
+ public String ipAddress;
+ @SuppressWarnings("unused")
+ public String dbClusterStatus;
+ @SuppressWarnings("unused")
+ public String dbPermissions;
+ }
+
+ private final String statusUp = "UP";
+ private final String statusDown = "DOWN";
+ private final String statusOk = "OK";
+
+ @RequestMapping(value = {"/portalApi/healthCheck"}, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheck(HttpServletRequest request, HttpServletResponse response) {
+ HealthStatus healthStatus = new HealthStatus(500, "");
+
+ // Return the status as 500 if it suspended due to manual fail over
+ if (HealthMonitor.isSuspended()) {
+ healthStatus.body = "Suspended";
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ MDC.put(EPCommonSystemProperties.RESPONSE_CODE,
+ Integer.toString(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));
+ return healthStatus;
+ }
+
+ try {
+ boolean overallStatus = true;
+
+ List<HealthStatusInfo> statusCollection = new ArrayList<HealthStatusInfo>();
+
+ HealthStatusInfo beInfo = new HealthStatusInfo("BE");
+ beInfo.hostName = EcompPortalUtils.getMyHostName();
+ beInfo.ipAddress = EcompPortalUtils.getMyIpAdddress();
+ if (!HealthMonitor.isBackEndUp()) {
+ overallStatus = false;
+ beInfo.healthCheckStatus = statusDown;
+ beInfo.description = "Check the logs for more details";
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHealthCheckError);
+ }
+ statusCollection.add(beInfo);
+
+ HealthStatusInfo feInfo = new HealthStatusInfo("FE");
+ if (!HealthMonitor.isFrontEndUp()) {
+ overallStatus = false;
+ feInfo.healthCheckStatus = statusDown;
+ feInfo.description = "Check the logs for more details";
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.FeHealthCheckError);
+ }
+ statusCollection.add(feInfo);
+
+ HealthStatusInfo dbInfo = new HealthStatusInfo("DB");
+ if (!HealthMonitor.isDatabaseUp()) {
+ overallStatus = false;
+ dbInfo.healthCheckStatus = statusDown;
+ dbInfo.description = "Check the logs for more details";
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeDaoSystemError);
+ }
+ if (!HealthMonitor.isDbPermissionsOk()) {
+ dbInfo.dbPermissions = "Problem, check the logs for more details";
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeDaoSystemError);
+ } else {
+ dbInfo.dbPermissions = statusOk;
+ }
+ statusCollection.add(dbInfo);
+
+ if (org.onap.portalapp.music.util.MusicUtil.isMusicEnable()) {
+ HealthStatusInfo CassandraStatusInfo = new HealthStatusInfo("Music-Cassandra");
+ //CassandraStatusInfo.hostName = EcompPortalUtils.getMyHostName();
+ CassandraStatusInfo.ipAddress = MusicUtil.getMyCassaHost();
+
+ if (!HealthMonitor.isCassandraStatusOk()) {
+ overallStatus = false;
+ CassandraStatusInfo.healthCheckStatus = statusDown;
+ CassandraStatusInfo.description = "Check the logs for more details";
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.MusicHealthCheckCassandraError);
+ }
+ statusCollection.add(CassandraStatusInfo);
+ }
+
+ String json = "";
+ try {
+ json = new Gson().toJson(statusCollection);
+ } catch (Exception e) {
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeInvalidJsonInput);
+ }
+ logger.info(EELFLoggerDelegate.debugLogger, json);
+
+ if (overallStatus) {
+ healthStatus = new HealthStatus(200, json);
+ } else {
+ healthStatus = new HealthStatus(500, json);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ MDC.put(EPCommonSystemProperties.RESPONSE_CODE, Integer.toString(healthStatus.statusCode));
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "healthCheck failed", e);
+ }
+
+ EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/healthCheck", "GET result =", response.getStatus());
+
+ return healthStatus;
+ }
+
+ @RequestMapping(value = {
+ "/portalApi/healthCheckSuspend"}, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheckSuspend(HttpServletRequest request, HttpServletResponse response) {
+ HealthStatus healthStatus = new HealthStatus(500, "Suspended for manual failover mechanism");
+
+ HealthMonitor.setSuspended(true);
+ healthStatus.statusCode = 200;
+
+ EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/healthCheckSuspend", "GET result =",
+ response.getStatus());
+
+ return healthStatus;
+ }
+
+ @RequestMapping(value = {
+ "/portalApi/healthCheckResume"}, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus healthCheckResume(HttpServletRequest request, HttpServletResponse response) {
+ HealthStatus healthStatus = new HealthStatus(500, "Resumed from manual failover mechanism");
+
+ HealthMonitor.setSuspended(false);
+ healthStatus.statusCode = 200;
+ EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/healthCheckResume", "GET result =",
+ response.getStatus());
+ return healthStatus;
+ }
+
+ @RequestMapping(value = {"/portalApi/ping"}, method = RequestMethod.GET, produces = "application/json")
+ public HealthStatus ping(HttpServletRequest request, HttpServletResponse response) {
+ HealthStatus healthStatus = new HealthStatus(200, "OK");
+ EcompPortalUtils.logAndSerializeObject(logger, "/portalApi/ping", "GET result =", response.getStatus());
+
+ return healthStatus;
+ }
+}
diff --git a/portal-BE/src/main/java/org/onap/portal/controller/ManifestController.java b/portal-BE/src/main/java/org/onap/portal/controller/ManifestController.java
new file mode 100644
index 00000000..ccf864cb
--- /dev/null
+++ b/portal-BE/src/main/java/org/onap/portal/controller/ManifestController.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+package org.onap.portal.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.Attributes;
+import javax.servlet.http.HttpServletRequest;
+import org.onap.portal.service.ManifestService;
+import org.onap.portalsdk.core.controller.RestrictedBaseController;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@EnableAspectJAutoProxy
+public class ManifestController {
+ //TODO extends RestrictedBaseController
+ private EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ManifestController.class);
+
+ private final ManifestService manifestService;
+
+ @Autowired
+ public ManifestController(ManifestService manifestService) {
+ this.manifestService = manifestService;
+ }
+
+ @RequestMapping(value = {"/portalApi/manifest"}, method = RequestMethod.GET, produces = "application/json")
+ @ResponseBody
+ public Map<String, Object> getManifest(HttpServletRequest request) {
+ Map<String, Object> response = new HashMap<String, Object>();
+ try {
+ Attributes attributes = manifestService.getWebappManifest();
+ response.put("manifest", attributes);
+ } catch (Exception ex) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getManifest: failed to read manifest", ex);
+ response.put("error", "failed to get manifest: " + ex.toString());
+ }
+ return response;
+ }
+
+}
diff --git a/portal-BE/src/main/java/org/onap/portal/scheduler/healthMonitor/HealthMonitor.java b/portal-BE/src/main/java/org/onap/portal/scheduler/healthMonitor/HealthMonitor.java
new file mode 100644
index 00000000..3b83e146
--- /dev/null
+++ b/portal-BE/src/main/java/org/onap/portal/scheduler/healthMonitor/HealthMonitor.java
@@ -0,0 +1,359 @@
+/*-
+ * ============LICENSE_START==========================================
+ * ONAP Portal
+ * ===================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ *
+ * Unless otherwise specified, all software contained herein is licensed
+ * under the Apache License, Version 2.0 (the "License");
+ * you may not use this software except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Unless otherwise specified, all documentation contained herein is licensed
+ * under the Creative Commons License, Attribution 4.0 Intl. (the "License");
+ * you may not use this documentation except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by/4.0/
+ *
+ * Unless required by applicable law or agreed to in writing, documentation
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * ============LICENSE_END============================================
+ *
+ *
+ */
+package org.onap.portal.scheduler.healthMonitor;
+
+import java.time.Instant;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.persistence.EntityManagerFactory;
+import lombok.NoArgsConstructor;
+import org.apache.zookeeper.client.FourLetterWordMain;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.onap.music.datastore.PreparedQueryObject;
+import org.onap.music.exceptions.MusicServiceException;
+import org.onap.music.main.MusicCore;
+import org.onap.music.main.MusicUtil;
+import org.onap.portal.logging.format.EPAppMessagesEnum;
+import org.onap.portal.logging.logic.EPLogUtil;
+import org.onap.portal.utils.EPCommonSystemProperties;
+import org.onap.portalapp.music.util.MusicProperties;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.onap.portalsdk.core.util.SystemProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.transaction.annotation.Transactional;
+
+
+@Transactional
+@Configuration
+@EnableAspectJAutoProxy
+@NoArgsConstructor
+public class HealthMonitor {
+ private static EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(HealthMonitor.class);
+ private Thread healthMonitorThread;
+ private static EntityManagerFactory entityManagerFactory;
+ private static boolean databaseUp;
+ private static boolean uebUp;
+ private static boolean frontEndUp;
+ private static boolean backEndUp;
+ private static boolean dbPermissionsOk;
+ private static boolean zookeeperStatusOk;
+ private static boolean cassandraStatusOk;
+ private static String application = "Portal";
+ private static boolean isSuspended = false;
+
+ @Autowired
+ public HealthMonitor(EntityManagerFactory entityManagerFactory) {
+ this.entityManagerFactory = entityManagerFactory;
+
+ }
+
+ private static void monitorEPHealth() {
+
+ int numIntervalsDatabaseHasBeenDown = 0;
+ int numIntervalsDatabasePermissionsIncorrect = 0;
+ int numIntervalsZookeeperNotHealthy = 0;
+ int numIntervalsCassandraNotHealthy = 0;
+
+ logger.debug(EELFLoggerDelegate.debugLogger, "monitorEPHealth thread started");
+
+
+ long sleepInterval = (Long
+ .parseLong(SystemProperties.getProperty(EPCommonSystemProperties.HEALTH_POLL_INTERVAL_SECONDS)) * 1000);
+ long numIntervalsBetweenAlerts = Long
+ .parseLong(SystemProperties.getProperty(EPCommonSystemProperties.HEALTHFAIL_ALERT_EVERY_X_INTERVALS));
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "monitorEPHealth: Polling health every " + sleepInterval + " milliseconds. Alerting every "
+ + (sleepInterval * numIntervalsBetweenAlerts) / 1000 + " seconds when component remains down.");
+
+ while (true) {
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "monitorEPHealth: Test Connection to all");
+ //
+ // Get DB status. If down, signal alert once every X intervals.
+ //
+ databaseUp = checkIfDatabaseUp();
+ if (databaseUp) {
+ if ((numIntervalsDatabaseHasBeenDown % numIntervalsBetweenAlerts) == 0) {
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "monitorEPHealth: database down, logging to error log to trigger alert.");
+ // Write a Log entry that will generate an alert
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHealthCheckMySqlError);
+ numIntervalsDatabaseHasBeenDown++;
+ } else {
+ numIntervalsDatabaseHasBeenDown = 0;
+ }
+ }
+
+ dbPermissionsOk = checkDatabasePermissions();
+ if (!dbPermissionsOk) {
+ if ((numIntervalsDatabasePermissionsIncorrect % numIntervalsBetweenAlerts) == 0) {
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "monitorEPHealth: database permissions incorrect, logging to error log to trigger alert.");
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.BeHealthCheckMySqlError);
+ numIntervalsDatabasePermissionsIncorrect++;
+ } else {
+ numIntervalsDatabasePermissionsIncorrect = 0;
+ }
+ }
+ if(org.onap.portalapp.music.util.MusicUtil.isMusicEnable()){
+ cassandraStatusOk = checkCassandraStatus();
+ if (!cassandraStatusOk) {
+ if ((numIntervalsCassandraNotHealthy % numIntervalsBetweenAlerts) == 0) {
+ logger.debug(EELFLoggerDelegate.debugLogger,
+ "monitorEPHealth: cluster nodes down, logging to error log to trigger alert.");
+ EPLogUtil.logEcompError(logger, EPAppMessagesEnum.MusicHealthCheckCassandraError);
+ numIntervalsCassandraNotHealthy++;
+ } else {
+ numIntervalsCassandraNotHealthy = 0;
+ }
+ }
+ }
+ frontEndUp = true;
+ backEndUp = true;
+
+ if (Thread.interrupted()) {
+ logger.info(EELFLoggerDelegate.errorLogger, "monitorEPHealth: thread interrupted");
+ break;
+ }
+
+ try {
+ Thread.sleep(sleepInterval);
+ } catch (InterruptedException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "monitorEPHealth: sleep interrupted", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ @PostConstruct
+ public void initHealthMonitor() {
+ healthMonitorThread = new Thread("EP HealthMonitor thread") {
+ @Override
+ public void run() {
+ try {
+ monitorEPHealth();
+ }
+ catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "healthMonitorThread failed", e);
+ }
+ }
+ };
+ healthMonitorThread.start();
+
+ }
+
+ @PreDestroy
+ public void closeHealthMonitor() {
+ this.healthMonitorThread.interrupt();
+ }
+
+ /**
+ * This routine checks whether the database can be read. In June 2017 we
+ * experimented with checking if the database can be WRITTEN. Writes failed
+ * with some regularity in a MariaDB Galera cluster, and in that
+ * environment, the resulting alerts in the log triggered a health monitor
+ * cron job to shut down the Tomcat instance. The root cause of the cluster
+ * write failures was not determined.
+ *
+ * @return true if the database can be read.
+ */
+ private static boolean checkIfDatabaseUp() {
+ boolean isUp = false;
+ Session localSession = null;
+ try {
+ localSession = entityManagerFactory.unwrap(SessionFactory.class).openSession();
+ if (localSession != null) {
+ String sql = "select app_name from fn_app where app_id=1";
+ Query query = localSession.createSQLQuery(sql);
+ @SuppressWarnings("unchecked")
+ List<String> queryList = query.list();
+ if (queryList != null) {
+ isUp = true;
+ }
+ }
+ } catch (Exception e) {
+ logger.debug(EELFLoggerDelegate.debugLogger, "checkIfDatabaseUp failed", e);
+ isUp = false;
+ } finally {
+ if (localSession != null)
+ localSession.close();
+ }
+ return isUp;
+ }
+
+ private static boolean checkZookeeperStatus() {
+
+ String[] zookeeperNodes = MusicUtil.getMyZkHost().split(",");
+ logger.info(EELFLoggerDelegate.applicationLogger, "MusicUtil.getMyZkHost()---- :" + MusicUtil.getMyZkHost());
+ for (String zookeeperNode : zookeeperNodes) {
+ try {
+ logger.info(EELFLoggerDelegate.applicationLogger, "server ip--zookeeper :" + zookeeperNode.trim());
+ String[] iport = zookeeperNode.split(":");
+ String zkNodeStatistics = FourLetterWordMain.send4LetterWord(iport[0].trim(),
+ Integer.parseInt(iport[1].trim()), "stat");
+ logger.info(EELFLoggerDelegate.applicationLogger,
+ "Getting Status for Zookeeper zkNodeStatistics :" + zkNodeStatistics);
+ if (!zkNodeStatistics.isEmpty()) {
+ String state = zkNodeStatistics.substring(zkNodeStatistics.indexOf("Mode:"),
+ zkNodeStatistics.indexOf("Node"));
+ logger.info(EELFLoggerDelegate.applicationLogger,
+
+ "Getting Status for zookeeper :" + zookeeperNode.trim() + ":------:" + state);
+ if (state.contains("leader") || state.contains("follower")) {
+ return true;
+ }
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "ZookeeperStatus Service is not responding", e.getCause());
+ }
+ }
+
+ return false;
+ }
+
+
+ private static boolean checkCassandraStatus() {
+ logger.info(EELFLoggerDelegate.applicationLogger, "Getting Status for Cassandra");
+ if (getAdminKeySpace()) {
+ return true;
+ } else {
+ logger.error(EELFLoggerDelegate.errorLogger, "Cassandra Service is not responding");
+ return false;
+ }
+ }
+
+ private static Boolean getAdminKeySpace() {
+ String musicKeySpace = MusicProperties.getProperty(MusicProperties.MUSIC_SESSION_KEYSPACE);
+ Instant creationTime = Instant.now();
+ PreparedQueryObject pQuery = new PreparedQueryObject();
+ pQuery.appendQueryString(
+ "UPDATE " + musicKeySpace + ".health_check SET creation_time = ? WHERE primary_id = ?");
+ pQuery.addValue(creationTime.toString());
+ pQuery.addValue(application);
+ try {
+ MusicCore.nonKeyRelatedPut(pQuery, MusicUtil.CRITICAL);
+ } catch (MusicServiceException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, e.getErrorMessage(), e);
+ return Boolean.FALSE;
+ }
+ return Boolean.TRUE;
+
+ }
+
+
+ private static boolean checkDatabasePermissions() {
+ boolean isUp = false;
+ Session localSession = null;
+ try {
+ localSession = entityManagerFactory.unwrap(SessionFactory.class).openSession();
+ if (localSession != null) {
+ String sql = "SHOW GRANTS FOR CURRENT_USER";
+ Query query = localSession.createSQLQuery(sql);
+ @SuppressWarnings("unchecked")
+ List<String> grantsList = query.list();
+ for (String str : grantsList) {
+ if ((str.toUpperCase().contains("ALL"))
+ || (str.toUpperCase().contains("DELETE") && str.toUpperCase().contains("SELECT")
+ && str.toUpperCase().contains("UPDATE") && str.toUpperCase().contains("INSERT"))) {
+ isUp = true;
+ break;
+ }
+ }
+ if (!isUp) {
+ logger.error(EELFLoggerDelegate.errorLogger,
+ "checkDatabasePermissions returning false. SHOW GRANTS FOR CURRENT_USER being dumped:");
+ for (String str : grantsList) {
+ logger.error(EELFLoggerDelegate.errorLogger, "grants output item = [" + str + "]");
+ }
+ }
+ }
+ } catch (Exception e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "checkDatabasePermissions failed", e);
+ if ((e.getCause() != null) && (e.getCause().getMessage() != null)) {
+ logger.error(EELFLoggerDelegate.errorLogger, "checkDatabasePermissions failure cause", e.getCause());
+ }
+ isUp = false;
+ } finally {
+ if (localSession != null) {
+ localSession.close();
+ }
+ }
+ return isUp;
+ }
+
+ public static boolean isDatabaseUp() {
+ return databaseUp;
+ }
+
+ public static boolean isUebUp() {
+ return uebUp;
+ }
+
+ public static boolean isFrontEndUp() {
+ return frontEndUp;
+ }
+
+ public static boolean isBackEndUp() {
+ return backEndUp;
+ }
+
+ public static boolean isDbPermissionsOk() {
+ return dbPermissionsOk;
+ }
+
+ public static boolean isZookeeperStatusOk() {
+ return zookeeperStatusOk;
+ }
+
+ public static boolean isCassandraStatusOk() {
+ return cassandraStatusOk;
+ }
+
+ public static boolean isSuspended() {
+ return isSuspended;
+ }
+
+ public static void setSuspended(boolean isSuspended) {
+ HealthMonitor.isSuspended = isSuspended;
+ }
+}
diff --git a/portal-BE/src/main/java/org/onap/portal/service/ManifestService.java b/portal-BE/src/main/java/org/onap/portal/service/ManifestService.java
new file mode 100644
index 00000000..eb823250
--- /dev/null
+++ b/portal-BE/src/main/java/org/onap/portal/service/ManifestService.java
@@ -0,0 +1,35 @@
+package org.onap.portal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import javax.servlet.ServletContext;
+import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+import org.springframework.stereotype.Service;
+
+@Service
+@EnableAspectJAutoProxy
+public class ManifestService {
+
+ @Autowired
+ ServletContext context;
+
+ public Attributes getWebappManifest() throws IOException {
+ EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(ManifestService.class);
+ // Path to resource on classpath
+ final String MANIFEST_RESOURCE_PATH = "/META-INF/MANIFEST.MF";
+ // Manifest is formatted as Java-style properties
+ try {
+ InputStream inputStream = context.getResourceAsStream(MANIFEST_RESOURCE_PATH);
+ Manifest manifest = new Manifest(inputStream);
+ inputStream.close();
+ return manifest.getMainAttributes();
+ } catch (IOException e) {
+ logger.error(EELFLoggerDelegate.errorLogger, "getWebappManifest: failed to read/find manifest");
+ throw e;
+ }
+ }
+}
diff --git a/portal-BE/src/main/resources/application.properties b/portal-BE/src/main/resources/application.properties
index b99840d2..c59fa413 100644
--- a/portal-BE/src/main/resources/application.properties
+++ b/portal-BE/src/main/resources/application.properties
@@ -1,4 +1,4 @@
-server.port=8080
+server.port=8081
spring.datasource.url=jdbc:mysql://portal-db:3306/testdb?createDatabaseIfNotExist=true&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
spring.datasource.driverClassName=org.mariadb.jdbc.Driver