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