Catalog alignment
[sdc.git] / catalog-be / src / main / java / org / openecomp / sdc / be / switchover / detector / SwitchoverDetector.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
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.switchover.detector;
22
23 import com.google.common.annotations.VisibleForTesting;
24 import org.apache.http.entity.ContentType;
25 import org.apache.http.entity.StringEntity;
26 import org.openecomp.sdc.be.config.BeEcompErrorManager;
27 import org.openecomp.sdc.be.config.Configuration.SwitchoverDetectorConfig;
28 import org.openecomp.sdc.be.config.ConfigurationManager;
29 import org.openecomp.sdc.common.http.client.api.HttpRequest;
30 import org.openecomp.sdc.common.log.wrappers.Logger;
31 import org.springframework.stereotype.Component;
32
33 import javax.annotation.PostConstruct;
34 import javax.annotation.PreDestroy;
35 import java.net.InetAddress;
36 import java.util.Properties;
37 import java.util.concurrent.ExecutorService;
38 import java.util.concurrent.Executors;
39 import java.util.concurrent.ScheduledExecutorService;
40 import java.util.concurrent.ScheduledFuture;
41 import java.util.concurrent.ThreadFactory;
42 import java.util.concurrent.TimeUnit;
43
44 @Component("switchover-detector")
45 public class SwitchoverDetector {
46
47     protected static String SWITCHOVER_DETECTOR_LOG_CONTEXT = "switchover.detector";
48
49     private SwitchoverDetectorConfig switchoverDetectorConfig;
50
51     private Properties authHeader = null;
52
53     private long detectorInterval = 60;
54
55     private int maxBeQueryAttempts = 3;
56
57     private int maxFeQueryAttempts = 3;
58
59     private Boolean beMatch = null;
60
61     private Boolean feMatch = null;
62
63     private static final Logger logger = Logger.getLogger(SwitchoverDetector.class);
64
65     private volatile String siteMode = SwitchoverDetectorState.UNKNOWN.getState();
66
67     private ScheduledFuture<?> scheduledFuture = null;
68
69     ScheduledExecutorService switchoverDetectorScheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
70         @Override
71         public Thread newThread(Runnable r) {
72             return new Thread(r, "Switchover-Detector-Task");
73         }
74     });
75
76     SwitchoverDetectorScheduledTask switchoverDetectorScheduledTask = null;
77
78     public enum SwitchoverDetectorState {
79
80         UNKNOWN("unknown"), ACTIVE("active"), STANDBY("standby");
81
82         private String state;
83
84         SwitchoverDetectorState(String state) {
85             this.state = state;
86         }
87
88         public String getState() {
89             return state;
90         }
91     }
92
93     public enum SwitchoverDetectorGroup {
94
95         BE_SET("beSet"), FE_SET("feSet");
96
97         private String group;
98
99         SwitchoverDetectorGroup(String group) {
100             this.group = group;
101         }
102
103         public String getGroup() {
104             return group;
105         }
106     }
107
108     public String getSiteMode() {
109         return siteMode;
110     }
111
112     public void setSiteMode(String mode) {
113         this.siteMode = mode;
114     }
115
116     private Boolean queryBe() {
117         return queryGss(switchoverDetectorConfig.getgBeFqdn(), switchoverDetectorConfig.getBeVip(), maxBeQueryAttempts);
118     }
119
120     private Boolean queryFe() {
121         return queryGss(switchoverDetectorConfig.getgFeFqdn(), switchoverDetectorConfig.getFeVip(), maxFeQueryAttempts);
122     }
123
124     private void initializeSiteMode() {
125         while (siteMode.equals(SwitchoverDetectorState.UNKNOWN.getState())) {
126
127             beMatch = queryBe();
128             feMatch = queryFe();
129
130             if (beMatch == feMatch && beMatch != null) {
131                 if (beMatch) {
132                     setSiteMode(SwitchoverDetectorState.ACTIVE.getState());
133                 } else {
134                     setSiteMode(SwitchoverDetectorState.STANDBY.getState());
135                 }
136             }
137         }
138     }
139
140     private Boolean queryGss(String fqdn, String vip, int maxAttempts) {
141
142         Boolean result = null;
143         int attempts = 0;
144
145         while (result == null && (++attempts < maxAttempts)) {
146             try {
147                 InetAddress inetAddress = InetAddress.getByName(fqdn);
148                 result = inetAddress.getHostAddress().equals(vip);
149
150             } catch (Exception e) {
151                 String message = e.getMessage();
152                 if (message == null) {
153                     message = e.getClass().getName();
154                 }
155                 logger.debug("Error occured during switchover detector query, Result is {}", message, e);
156             }
157         }
158         if (null == result) {
159             BeEcompErrorManager.getInstance().logFqdnResolveError(SWITCHOVER_DETECTOR_LOG_CONTEXT, "host " + fqdn + " not resolved after " + attempts + " attempts");
160         }
161         return result;
162     }
163
164     public class SwitchoverDetectorScheduledTask implements Runnable {
165
166         public SwitchoverDetectorScheduledTask() {
167
168         }
169
170         @Override
171         public void run() {
172             logger.trace("Executing Switchover Detector Task - Start");
173
174             initializeSiteMode();
175
176             Boolean beRes = queryBe();
177             Boolean feRes = queryFe();
178
179             if (null == beRes || null == feRes) {
180                 return;
181             }
182
183             Boolean updateRequired = siteMode.equals(SwitchoverDetectorState.STANDBY.getState()) && (beRes || feRes) && (beMatch != beRes || feMatch != feRes);
184             Boolean prevModeStandby = siteMode.equals(SwitchoverDetectorState.STANDBY.getState());
185
186             updateSiteModeAndPriority(beRes && feRes, prevModeStandby, updateRequired);
187
188             beMatch = beRes;
189             feMatch = feRes;
190         }
191
192         ExecutorService switchoverDetectorExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
193             @Override
194             public Thread newThread(Runnable r) {
195                 return new Thread(r, "Switchover-Detector-Thread");
196             }
197         });
198
199         private void updateSiteModeAndPriority(Boolean bothMatch, Boolean previousModeStandby, Boolean updateRequired) {
200             if (bothMatch && previousModeStandby) {
201                 logger.trace("Site switch over was done. Site is now in active mode");
202                 setSiteMode(SwitchoverDetectorState.ACTIVE.getState());
203                 BeEcompErrorManager.getInstance().logSiteSwitchoverInfo(SWITCHOVER_DETECTOR_LOG_CONTEXT, siteMode);
204             } else if (!bothMatch && !previousModeStandby) {
205                 logger.trace("Site switch over was done. Site is now in stand-by mode");
206                 setSiteMode(SwitchoverDetectorState.STANDBY.getState());
207                 BeEcompErrorManager.getInstance().logSiteSwitchoverInfo(SWITCHOVER_DETECTOR_LOG_CONTEXT, siteMode);
208             }
209             if (updateRequired) {
210                 changeSitePriority(SwitchoverDetectorGroup.BE_SET.getGroup());
211                 changeSitePriority(SwitchoverDetectorGroup.FE_SET.getGroup());
212                 publishNetwork();
213             }
214         }
215
216         private void changeSitePriority(String groupToSet) {
217
218             String url = switchoverDetectorConfig.getGroups().get(groupToSet).getChangePriorityUrl();
219             String body = switchoverDetectorConfig.getGroups().get(groupToSet).getChangePriorityBody();
220
221             try {
222                 HttpRequest.put(url, authHeader, new StringEntity(body, ContentType.APPLICATION_JSON));
223             } catch (Exception e) {
224                 String message = e.getMessage();
225                 if (message == null) {
226                     message = e.getClass().getName();
227                 }
228                 logger.debug("Error occured during change site priority request, Result is {}", message, e);
229             }
230
231         }
232
233         private void publishNetwork() {
234
235             String url = switchoverDetectorConfig.getPublishNetworkUrl();
236             String body = switchoverDetectorConfig.getPublishNetworkBody();
237             try {
238                 HttpRequest.post(url, authHeader, new StringEntity(body, ContentType.APPLICATION_JSON));
239             } catch (Exception e) {
240                 String message = e.getMessage();
241                 if (message == null) {
242                     message = e.getClass().getName();
243                 }
244                 logger.debug("Error occured during publish network request, Result is {}", message, e);
245             }
246         }
247
248     }
249
250     @VisibleForTesting
251     void setSwitchoverDetectorConfig(SwitchoverDetectorConfig switchoverDetectorConfig) {
252         this.switchoverDetectorConfig = switchoverDetectorConfig;
253     }
254
255     @PostConstruct
256     private void init() {
257         logger.info("Enter init method of SwitchoverDetector");
258
259         switchoverDetectorConfig = ConfigurationManager.getConfigurationManager().getConfiguration().getSwitchoverDetector();
260
261         if (!switchoverDetectorConfig.getEnabled()) {
262             logger.info("switchover detector service is disabled");
263             return;
264         }
265
266         Long detectorIntervalConfig = switchoverDetectorConfig.getInterval();
267         if (detectorIntervalConfig != null) {
268             detectorInterval = detectorIntervalConfig.longValue();
269         }
270
271         Integer maxAttempts = switchoverDetectorConfig.getBeResolveAttempts();
272         if (maxAttempts != null) {
273             maxBeQueryAttempts = maxAttempts.intValue();
274         }
275         maxAttempts = switchoverDetectorConfig.getFeResolveAttempts();
276         if (maxAttempts != null) {
277             maxFeQueryAttempts = maxAttempts.intValue();
278         }
279
280         logger.info("switchover detector service is enabled, interval is {} seconds", detectorInterval);
281
282         this.switchoverDetectorScheduledTask = new SwitchoverDetectorScheduledTask();
283         startSwitchoverDetectorTask();
284         logger.trace("Exit init method of SwitchoverDetector");
285
286     }
287
288     @PreDestroy
289     private void destroy() {
290
291         if (scheduledFuture != null) {
292             scheduledFuture.cancel(true);
293             scheduledFuture = null;
294         }
295
296         if (switchoverDetectorScheduler != null) {
297             switchoverDetectorScheduler.shutdown();
298         }
299
300     }
301
302     public void startSwitchoverDetectorTask() {
303         if (this.scheduledFuture == null) {
304             this.scheduledFuture = this.switchoverDetectorScheduler.scheduleAtFixedRate(switchoverDetectorScheduledTask, 0, detectorInterval, TimeUnit.SECONDS);
305         }
306     }
307
308 }