Catalog alignment
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / components / health / PortalHealthCheckBuilder.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2020 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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.openecomp.sdc.be.components.health;
22
23 import com.google.common.annotations.VisibleForTesting;
24 import org.apache.commons.lang.StringUtils;
25 import org.onap.portalsdk.core.onboarding.exception.CipherUtilException;
26 import org.onap.portalsdk.core.onboarding.util.PortalApiProperties;
27 import org.openecomp.sdc.be.config.Configuration;
28 import org.openecomp.sdc.be.config.Configuration.EcompPortalConfig;
29 import org.openecomp.sdc.be.config.ConfigurationManager;
30 import org.openecomp.sdc.be.ecomp.PortalPropertiesEnum;
31 import org.openecomp.sdc.common.api.Constants;
32 import org.openecomp.sdc.common.api.HealthCheckInfo;
33 import org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus;
34 import org.openecomp.sdc.common.http.client.api.HttpExecuteException;
35 import org.openecomp.sdc.common.http.client.api.HttpRequest;
36 import org.openecomp.sdc.common.http.client.api.HttpResponse;
37 import org.openecomp.sdc.common.http.config.HttpClientConfig;
38 import org.openecomp.sdc.common.http.config.Timeouts;
39 import org.openecomp.sdc.common.log.wrappers.Logger;
40 import org.springframework.stereotype.Component;
41
42 import javax.annotation.PostConstruct;
43 import javax.annotation.PreDestroy;
44 import javax.ws.rs.core.HttpHeaders;
45 import javax.ws.rs.core.MediaType;
46 import java.security.InvalidParameterException;
47 import java.util.Base64;
48 import java.util.Properties;
49 import java.util.UUID;
50 import java.util.concurrent.Executors;
51 import java.util.concurrent.ScheduledExecutorService;
52 import java.util.concurrent.ScheduledFuture;
53 import java.util.concurrent.TimeUnit;
54
55 import static org.apache.http.HttpStatus.SC_OK;
56 import static org.onap.portalsdk.core.onboarding.util.CipherUtil.decryptPKC;
57 import static org.openecomp.sdc.common.api.Constants.HC_COMPONENT_ECOMP_PORTAL;
58 import static org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus.DOWN;
59 import static org.openecomp.sdc.common.api.HealthCheckInfo.HealthCheckStatus.UP;
60
61 @Component("portalHealthCheckBusinessLogic")
62 public class PortalHealthCheckBuilder {
63
64     private static final Logger log = Logger.getLogger(HealthCheckBusinessLogic.class.getName());
65     private static final String PORTAL_NOT_AVAILABLE = HC_COMPONENT_ECOMP_PORTAL + " is not available";
66     private static final String PROPERTY_NOT_SET = "Property is not found %s";
67     private static final String CONFIG_IS_MISSING = HC_COMPONENT_ECOMP_PORTAL + " health check configuration is missing";
68     private static final String PORTAL_ERROR = HC_COMPONENT_ECOMP_PORTAL + " responded with %s status code";
69     private String decryptedPortalUser;
70     private String decryptedPortalPass;
71     private EcompPortalConfig configuration = null ;
72     private long healthCheckReadTimeout = 20;
73     private long reconnectInterval = 5;
74     private HealthCheckScheduledTask healthCheckScheduledTask = null ;
75     private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
76     private ScheduledFuture<?> scheduledFuture = null;
77     private HealthCheckInfo healthCheckInfo = new HealthCheckInfo
78             (HC_COMPONENT_ECOMP_PORTAL, HealthCheckStatus.DOWN, null, CONFIG_IS_MISSING, null);
79
80     @VisibleForTesting
81     PortalHealthCheckBuilder init(EcompPortalConfig configuration) throws CipherUtilException {
82         log.trace("Enter init method of Portal healthcheck");
83         decryptedPortalUser = decryptPKC
84                 (getPortalProperty(PortalPropertiesEnum.USER.value()));
85         decryptedPortalPass = decryptPKC
86                 (getPortalProperty(PortalPropertiesEnum.PASSWORD.value()));
87         synchronized (PortalHealthCheckBuilder.class){
88             if (configuration != null) {
89                 Integer pollingInterval = configuration.getPollingInterval();
90                 if (pollingInterval != null && pollingInterval != 0) {
91                     reconnectInterval = pollingInterval;
92                 }
93                 Integer healthCheckReadTimeoutConfig = configuration.getTimeoutMs();
94                 if (healthCheckReadTimeoutConfig != null) {
95                     this.healthCheckReadTimeout = healthCheckReadTimeoutConfig;
96                 }
97                 this.healthCheckScheduledTask = new HealthCheckScheduledTask(configuration);
98                 startHealthCheckTask(true);
99             }
100             else {
101                 log.error("ECOMP Portal health check configuration is missing.");
102             }
103         }
104         log.trace("Exit init method of Portal healthcheck");
105         return this;
106     }
107
108     @PostConstruct
109     public PortalHealthCheckBuilder init() throws CipherUtilException {
110         return init(ConfigurationManager.getConfigurationManager().getConfiguration().getEcompPortal());
111     }
112
113
114     @PreDestroy
115     protected void destroy() {
116         if (scheduledFuture != null) {
117             scheduledFuture.cancel(true);
118             scheduledFuture = null;
119         }
120         if (scheduler != null) {
121             scheduler.shutdown();
122         }
123     }
124
125     /**
126      * Start health check task.
127      *
128      * @param startTask
129      */
130     private void startHealthCheckTask(boolean startTask) {
131         synchronized (PortalHealthCheckBuilder.class){
132             if (startTask && this.scheduledFuture == null) {
133                 this.scheduledFuture = this.scheduler.scheduleAtFixedRate(this.healthCheckScheduledTask , 0, reconnectInterval, TimeUnit.SECONDS);
134             }
135         }
136     }
137
138     @VisibleForTesting
139     void runTask() {
140         healthCheckScheduledTask.run();
141     }
142
143     public HealthCheckInfo getHealthCheckInfo() {
144         return healthCheckInfo;
145     }
146
147     /**
148      * Health Check Task Scheduler - infinite check.
149      */
150     public class HealthCheckScheduledTask implements Runnable {
151         private final EcompPortalConfig config;
152         String healthCheckUrl = buildPortalHealthCheckUrl();
153         HealthCheckStatus healthCheckStatus = DOWN;
154         String componentName = HC_COMPONENT_ECOMP_PORTAL;
155         String description;
156         final int timeout = 3000;
157
158         HealthCheckScheduledTask(final EcompPortalConfig config){
159             this.config = config;
160         }
161         @Override
162         public void run() {
163             if (healthCheckUrl != null) {
164                 try {
165                     int statusCode = getStatusCode(healthCheckUrl, timeout);
166                     log.trace("{} Health Check response code: {}", componentName, statusCode);
167                     if (statusCode != SC_OK) {
168                         description = String.format(PORTAL_ERROR, statusCode);
169                     } else {
170                         healthCheckStatus = UP;
171                         description = "OK";
172                     }
173                 } catch (Exception e) {
174                     log.error("{} is not available: ", componentName, e.getMessage());
175                     description = PORTAL_NOT_AVAILABLE;
176                 }
177             } else {
178                 description = CONFIG_IS_MISSING;
179             }
180
181             healthCheckInfo.setHealthCheckStatus(healthCheckStatus);
182             healthCheckInfo.setDescription(description);
183         }
184     }
185
186     private static String getPortalProperty(String key) {
187         String value = PortalApiProperties.getProperty(key);
188         if (StringUtils.isEmpty(value)) {
189             throw new InvalidParameterException(String.format(PROPERTY_NOT_SET, key));
190         }
191         return value;
192     }
193
194     String buildPortalHealthCheckUrl() {
195         final String hcUrl = "%s://%s:%s%s";
196         Configuration.EcompPortalConfig configuration = ConfigurationManager.getConfigurationManager().getConfiguration().getEcompPortal();
197         if (configuration != null) {
198             return String.format(hcUrl, configuration.getProtocol(), configuration.getHost(),
199                     configuration.getPort(), configuration.getHealthCheckUri());
200         }
201         log.error("ECOMP Portal health check configuration is missing.");
202         return null;
203     }
204
205     private Properties createHeaders(){
206         Properties headers = new Properties();
207         String encodedBasicAuthCred = Base64.getEncoder()
208                 .encodeToString((decryptedPortalUser + ":" +
209                         decryptedPortalPass)
210                         .getBytes());
211         headers.put(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON);
212         headers.put(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON);
213         headers.put(Constants.X_TRANSACTION_ID_HEADER, UUID.randomUUID().toString());
214         headers.put("Authorization", "Basic " + encodedBasicAuthCred);
215         headers.put("cache-control", "no-cache");
216         headers.put("uebkey", PortalApiProperties.getProperty("ueb_app_key"));
217         return headers;
218     }
219
220     int getStatusCode(String healthCheckUrl, int timeout) throws HttpExecuteException {
221         HttpResponse<String> httpResponse = HttpRequest.get(healthCheckUrl, createHeaders(), new HttpClientConfig(new Timeouts(timeout, timeout)));
222         return httpResponse.getStatusCode();
223     }
224
225     @VisibleForTesting
226     public EcompPortalConfig getConfiguration() {
227         return ConfigurationManager.getConfigurationManager().getConfiguration().getEcompPortal();
228     }
229
230 }