2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Modifications Copyright (c) 2019 Samsung
8 * ================================================================================
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 * ============LICENSE_END=========================================================
23 package org.onap.so.apihandlerinfra;
27 import java.util.Collections;
28 import java.util.List;
29 import java.util.stream.Collectors;
30 import javax.annotation.PostConstruct;
31 import javax.transaction.Transactional;
32 import javax.ws.rs.DefaultValue;
33 import javax.ws.rs.GET;
34 import javax.ws.rs.Path;
35 import javax.ws.rs.Produces;
36 import javax.ws.rs.QueryParam;
37 import javax.ws.rs.container.ContainerRequestContext;
38 import javax.ws.rs.core.Context;
39 import javax.ws.rs.core.Response;
40 import javax.ws.rs.core.UriBuilder;
41 import org.apache.http.HttpStatus;
42 import org.onap.so.apihandlerinfra.HealthCheckConfig.Endpoint;
43 import org.onap.so.logger.LoggingAnchor;
44 import org.onap.so.logger.MessageEnum;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.springframework.beans.factory.annotation.Autowired;
48 import org.springframework.core.env.Environment;
49 import org.springframework.http.HttpEntity;
50 import org.springframework.http.HttpHeaders;
51 import org.springframework.http.HttpMethod;
52 import org.springframework.http.MediaType;
53 import org.springframework.http.ResponseEntity;
54 import org.springframework.stereotype.Component;
55 import org.springframework.web.client.RestTemplate;
56 import io.swagger.v3.oas.annotations.OpenAPIDefinition;
57 import io.swagger.v3.oas.annotations.Operation;
58 import io.swagger.v3.oas.annotations.info.Info;
59 import io.swagger.v3.oas.annotations.media.ArraySchema;
60 import io.swagger.v3.oas.annotations.media.Content;
61 import io.swagger.v3.oas.annotations.media.Schema;
62 import io.swagger.v3.oas.annotations.responses.ApiResponse;
66 @Path("/globalhealthcheck")
67 @OpenAPIDefinition(info = @Info(title = "/globalhealthcheck", description = "APIH Infra Global Health Check"))
68 public class GlobalHealthcheckHandler {
69 private static Logger logger = LoggerFactory.getLogger(GlobalHealthcheckHandler.class);
70 protected static final String CONTEXTPATH_PROPERTY = "management.endpoints.web.base-path";
71 protected static final String PROPERTY_DOMAIN = "mso.health";
72 protected static final String CATALOGDB_PROPERTY = PROPERTY_DOMAIN + ".endpoints.catalogdb";
73 protected static final String REQUESTDB_PROPERTY = PROPERTY_DOMAIN + ".endpoints.requestdb";
74 protected static final String SDNC_PROPERTY = PROPERTY_DOMAIN + ".endpoints.sdnc";
75 protected static final String OPENSTACK_PROPERTY = PROPERTY_DOMAIN + ".endpoints.openstack";
76 protected static final String BPMN_PROPERTY = PROPERTY_DOMAIN + ".endpoints.bpmn";
77 protected static final String ASDC_PROPERTY = PROPERTY_DOMAIN + ".endpoints.asdc";
78 protected static final String REQUESTDBATTSVC_PROPERTY = PROPERTY_DOMAIN + ".endpoints.requestdbattsvc";
79 protected static final String MSO_AUTH_PROPERTY = PROPERTY_DOMAIN + ".auth";
80 protected static final String DEFAULT_PROPERTY_VALUE = "";
83 private String actuatorContextPath;
86 private Environment env;
89 private RestTemplate restTemplate;
92 private HealthCheckConfig config;
94 private static final String HEALTH = "/health";
96 private String msoAuth;
99 protected void init() {
100 actuatorContextPath = env.getProperty(CONTEXTPATH_PROPERTY, String.class, DEFAULT_PROPERTY_VALUE);
101 msoAuth = env.getProperty(MSO_AUTH_PROPERTY, String.class, DEFAULT_PROPERTY_VALUE);
105 @Produces("application/json")
106 @Operation(description = "Performing global health check", responses = @ApiResponse(
107 content = @Content(array = @ArraySchema(schema = @Schema(implementation = Response.class)))))
109 public Response globalHealthcheck(@DefaultValue("true") @QueryParam("enableBpmn") boolean enableBpmn,
110 @Context ContainerRequestContext requestContext) {
111 Response HEALTH_CHECK_RESPONSE = null;
112 // Build internal response object
113 HealthCheckResponse rsp = new HealthCheckResponse();
116 // Generated RequestId
117 String requestId = requestContext.getProperty("requestId").toString();
118 logger.info(LoggingAnchor.TWO, MessageEnum.APIH_GENERATED_REQUEST_ID.toString(), requestId);
120 List<Endpoint> endpoints = config.getEndpoints().stream().filter(item -> {
121 if (!enableBpmn && SoSubsystems.BPMN.equals(item.getSubsystem())) {
126 }).collect(Collectors.toList());
128 for (Endpoint endpoint : endpoints) {
129 rsp.getSubsystems().add(querySubsystemHealth(endpoint));
133 rsp.setMessage(String.format("HttpStatus: %s", HttpStatus.SC_OK));
134 logger.info(rsp.toString());
136 HEALTH_CHECK_RESPONSE = Response.status(HttpStatus.SC_OK).entity(rsp).build();
138 } catch (Exception ex) {
139 logger.error("Exception occurred", ex);
140 rsp.setMessage(ex.getMessage());
141 HEALTH_CHECK_RESPONSE = Response.status(HttpStatus.SC_INTERNAL_SERVER_ERROR).entity(rsp).build();
144 return HEALTH_CHECK_RESPONSE;
147 protected HttpEntity<String> buildHttpEntityForRequest() {
148 HttpHeaders headers = new HttpHeaders();
149 headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
150 headers.set(HttpHeaders.CONTENT_TYPE, "application/json");
151 headers.set(HttpHeaders.AUTHORIZATION, msoAuth);
152 HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
156 protected HealthCheckSubsystem querySubsystemHealth(Endpoint subsystem) {
157 HealthCheckStatus status = HealthCheckStatus.DOWN;
158 URI uri = subsystem.getUri();
160 // get port number for the subsystem
161 // build final endpoint url
162 uri = UriBuilder.fromUri(subsystem.getUri()).path(actuatorContextPath).path(HEALTH).build();
163 logger.info("Calculated URL: {}", uri);
165 ResponseEntity<SubsystemHealthcheckResponse> result = restTemplate.exchange(uri, HttpMethod.GET,
166 buildHttpEntityForRequest(), SubsystemHealthcheckResponse.class);
168 status = processResponseFromSubsystem(result, subsystem);
171 } catch (Exception ex) {
172 logger.error("Exception occured in GlobalHealthcheckHandler.querySubsystemHealth() ", ex);
175 return new HealthCheckSubsystem(subsystem.getSubsystem(), uri, status);
178 protected HealthCheckStatus processResponseFromSubsystem(ResponseEntity<SubsystemHealthcheckResponse> result,
180 if (result == null || result.getStatusCodeValue() != HttpStatus.SC_OK) {
181 logger.error(String.format("Globalhealthcheck: checking subsystem: %s failed ! result object is: %s",
182 endpoint.getSubsystem(), result == null ? "NULL" : result));
183 return HealthCheckStatus.DOWN;
186 SubsystemHealthcheckResponse body = result.getBody();
188 String status = body.getStatus();
189 if ("UP".equalsIgnoreCase(status)) {
190 return HealthCheckStatus.UP;
192 logger.error("{}, query health endpoint did not return UP status!", endpoint.getSubsystem());
193 return HealthCheckStatus.DOWN;