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