Merge "Fix for Bug 3387 - Delete VPN should clear corresponding VrfTable in FIB DS"
[vpnservice.git] / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / bgpmanager / BgpManager.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.bgpmanager;
9
10
11 import java.net.SocketTimeoutException;
12 import java.util.*;
13 import java.util.concurrent.ConcurrentMap;
14 import java.util.concurrent.CountDownLatch;
15
16 import org.apache.thrift.TException;
17 import org.opendaylight.bgpmanager.thrift.client.globals.Route;
18 import org.opendaylight.bgpmanager.thrift.client.implementation.BgpRouter;
19 import org.opendaylight.bgpmanager.thrift.server.implementation.BgpThriftService;
20 import org.opendaylight.bgpmanager.thrift.exceptions.BgpRouterException;
21 import org.opendaylight.bgpmanager.api.IBgpManager;
22 import org.opendaylight.bgpmanager.globals.BgpConfiguration;
23 import org.opendaylight.bgpmanager.globals.BgpConstants;
24
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
28 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
29
30 import org.osgi.framework.Bundle;
31 import org.osgi.framework.BundleContext;
32 import org.osgi.framework.FrameworkUtil;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 public class BgpManager implements BindingAwareProvider, AutoCloseable, IBgpManager {
37
38     private static final Logger LOGGER = LoggerFactory.getLogger(BgpManager.class);
39     private BgpConfigurationManager bgpConfigurationMgr;
40     private FibDSWriter fibDSWriter;
41     private BgpConfiguration    bgpConfiguration = new BgpConfiguration();
42     private BgpRouter           bgpThriftClient;
43     private BgpThriftService    bgpThriftService;
44     private boolean             isBgpInitialized = false;
45     private boolean             hasBgpServiceStarted = false;
46     private String                              bgpHost;
47     private int                                 bgpPort;
48
49
50     private String getCustomConfig(String var, String def) {
51         Bundle b = FrameworkUtil.getBundle(this.getClass());
52         BundleContext context = null;
53         if (b != null) {
54             context = b.getBundleContext();
55         }
56         if (context != null)
57             return context.getProperty(var);
58         else
59             return def;
60
61     }
62
63     private void initializeBGPCommunication() {
64         //start our side of thrift server
65         bgpThriftService = new BgpThriftService(this, fibDSWriter);
66         bgpThriftService.start();
67
68         //start bgp thrift client connection
69         bgpThriftClient = new BgpRouter();
70
71         bgpHost = getCustomConfig(BgpConstants.BGP_SPEAKER_HOST_NAME, BgpConstants.DEFAULT_BGP_HOST_NAME);
72         bgpPort = BgpConstants.DEFAULT_BGP_THRIFT_PORT;
73
74         configureBgpServer(bgpHost, bgpPort);
75         try {
76             connectToServer(bgpHost, bgpPort);
77         } catch (Exception e) {
78             return;
79         }
80
81         isBgpInitialized = true;
82         //notify();       //notify all threads waiting for bgp init
83
84     }
85
86     public synchronized void waitForBgpInit() {
87         if(!isBgpInitialized) {
88             try {
89                 wait();
90             } catch (InterruptedException e) {
91                 LOGGER.error("InterruptedException while waiting for Bgp connection to initialize");
92                 return;
93             }
94         }
95     }
96
97     public void startBgpService() throws TException {
98         if(bgpThriftClient == null) {
99             LOGGER.error("Start Bgp Service - bgpThriftClient is null. Unable to start BGP service.");
100             return;
101         }
102
103         // Now try start bgp - if bgp is already Active, it will tell us, nothing to do then
104         try {
105             bgpThriftClient.startBgp((int)bgpConfiguration.getAsNum(), bgpConfiguration.getRouterId());
106             LOGGER.debug("Started BGP with AS number " + (int)bgpConfiguration.getAsNum() + " and router id " + bgpConfiguration.getRouterId());
107         } catch (BgpRouterException be) {
108             if(be.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
109                 LOGGER.info("bgp server already active");
110                 return;
111             }
112             else if(be.getErrorCode() == BgpRouterException.BGP_ERR_NOT_INITED) {
113                 LOGGER.error("bgp server connection not initialized.");
114                 reInitConn();
115                 return;
116             }
117             else {
118                 LOGGER.error("application error while starting bgp server " + be.getErrorCode());
119                 return;
120             }
121
122         }  catch (TException t) {
123             LOGGER.error("Could not set up thrift connection with bgp server");
124             LOGGER.debug("Transport error while starting bgp server ", t);
125             reInitConn();
126             throw t;
127         } catch (Exception e) {
128             LOGGER.error("Error while starting bgp server");
129             LOGGER.debug("Bgp Service not started due to exception", e);
130             return;
131         }
132
133         hasBgpServiceStarted = true;
134
135     }
136
137     @Override
138     public void onSessionInitiated(ProviderContext session) {
139         LOGGER.info("BgpManager Session Initiated");
140         try {
141             final DataBroker dataBroker = session.getSALService(DataBroker.class);
142             bgpConfigurationMgr = new BgpConfigurationManager(dataBroker, bgpConfiguration, this);
143             fibDSWriter = new FibDSWriter(dataBroker);
144         } catch (Exception e) {
145             LOGGER.error("Error initializing services", e);
146         }
147
148         initializeBGPCommunication();
149     }
150
151
152    @Override
153     public void close() throws Exception {
154         LOGGER.info("BgpManager Closed");
155
156        //close the client and server ends of the thrift communication
157        if(bgpThriftClient != null)
158            bgpThriftClient.disconnect();
159        bgpThriftService.stop();
160
161
162    }
163
164     private void setBgpServerDetails() {
165         if(bgpThriftClient != null)
166             bgpThriftClient.setBgpServer(bgpHost, bgpPort);
167     }
168
169     private void configureBgpServer(String bgpServer, int bgpPort) {
170         bgpConfiguration.setBgpServer(bgpServer);
171         bgpConfiguration.setBgpPort(bgpPort);
172         setBgpServerDetails();
173     }
174
175     protected void addNeighbor(String ipAddress, long asNum) throws TException {
176         if(bgpThriftClient == null) {
177             LOGGER.error("Add BGP Neighbor - bgpThriftClient is null. Unable to add BGP Neighbor.");
178             return;
179         }
180
181         try {
182             bgpThriftClient.addNeighbor(ipAddress, (int) asNum);
183         } catch (BgpRouterException b) {
184             LOGGER.error("Failed to add BGP neighbor " + ipAddress + " due to BgpRouter Exception number " + b.getErrorCode());
185             LOGGER.debug("BgpRouterException trace ", b);
186         } catch (TException t) {
187             LOGGER.error(String.format("Failed adding neighbor %s due to Transport error", ipAddress));
188             reInitConn();
189             throw t;
190         } catch (Exception e) {
191             LOGGER.error(String.format("Failed adding neighbor %s", ipAddress));
192         }
193     }
194
195
196     protected void deleteNeighbor(String ipAddress) throws TException {
197         if(bgpThriftClient == null) {
198             LOGGER.error("Delete BGP Neighbor - bgpThriftClient is null. Unable to delete BGP Neighbor.");
199             return;
200         }
201
202         try {
203             bgpThriftClient.delNeighbor(ipAddress);
204         } catch (BgpRouterException b) {
205             LOGGER.error("Failed to delete BGP neighbor " + ipAddress + "due to BgpRouter Exception number " + b.getErrorCode());
206             LOGGER.debug("BgpRouterException trace ", b);
207         }catch (TException t) {
208             LOGGER.error(String.format("Failed deleting neighbor %s due to Transport error", ipAddress));
209             reInitConn();
210             throw t;
211         } catch (Exception e) {
212             LOGGER.error(String.format("Failed deleting neighbor %s", ipAddress));
213         }
214     }
215
216
217     @Override
218     public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts) throws Exception {
219         if(bgpThriftClient == null) {
220             LOGGER.error("Add BGP vrf - bgpThriftClient is null. Unable to add BGP vrf.");
221             return;
222         }
223         try {
224             bgpThriftClient.addVrf(rd, new ArrayList<>(importRts), new ArrayList<>(exportRts));
225         } catch (BgpRouterException b) {
226             LOGGER.error("Failed to add BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
227             LOGGER.debug("BgpRouterException trace ", b);
228             throw b;
229         } catch (TException t) {
230             LOGGER.error(String.format("Failed adding vrf %s due to Transport error", rd));
231             reInitConn();
232             throw t;
233         } catch (Exception e) {
234             LOGGER.error(String.format("Failed adding vrf %s", rd));
235             throw e;
236         }
237     }
238
239     @Override
240     public void deleteVrf(String rd) throws Exception {
241         if(bgpThriftClient == null || !hasBgpServiceStarted) {
242             LOGGER.debug("Delete BGP vrf - Unable to delete BGP vrf in BGP Server. Removing Vrf from local DS");
243             fibDSWriter.removeVrfFromDS(rd);
244             return;
245         }
246
247         try {
248             bgpThriftClient.delVrf(rd);
249             fibDSWriter.removeVrfFromDS(rd);
250         } catch (BgpRouterException b) {
251             LOGGER.error("Failed to delete BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
252             LOGGER.debug("BgpRouterException trace ", b);
253             throw b;
254         } catch (TException t) {
255             LOGGER.error(String.format("Failed deleting vrf %s due to Transport error", rd));
256             reInitConn();
257             throw t;
258         } catch (Exception e) {
259             LOGGER.error(String.format("Failed deleting vrf %s", rd));
260             throw e;
261         }
262     }
263
264     @Override
265     public void addPrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception {
266
267         if(bgpThriftClient == null || !hasBgpServiceStarted) {
268             fibDSWriter.addFibEntryToDS(rd, prefix, nextHop, vpnLabel);
269             return;
270         }
271
272         try {
273             bgpThriftClient.addPrefix(rd, prefix, nextHop, vpnLabel);
274         } catch (BgpRouterException b) {
275             LOGGER.error("Failed to add BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
276             LOGGER.debug("BgpRouterException trace ", b);
277             throw b;
278         } catch (TException t) {
279             LOGGER.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d due to Transport error",
280                 rd, prefix, nextHop, vpnLabel));
281             reInitConn();
282             throw t;
283         } catch (Exception e) {
284             LOGGER.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d",
285                 rd, prefix, nextHop, vpnLabel));
286             throw e;
287         }
288     }
289
290
291     @Override
292     public void deletePrefix(String rd, String prefix) throws Exception {
293         if(bgpThriftClient == null || !hasBgpServiceStarted) {
294             fibDSWriter.removeFibEntryFromDS(rd, prefix);
295             return;
296         }
297
298         try {
299             bgpThriftClient.delPrefix(rd, prefix);
300         } catch (BgpRouterException b) {
301             LOGGER.error("Failed to delete BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
302             LOGGER.debug("BgpRouterException trace ", b);
303             throw b;
304         } catch (TException t) {
305             LOGGER.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s due to Transport error",
306                 rd, prefix));
307             reInitConn();
308             throw t;
309         } catch (Exception e) {
310             LOGGER.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s",
311                 rd, prefix));
312             throw e;
313         }
314     }
315
316     private void connectToServer(String host, int port) throws Exception {
317
318         bgpHost = host;
319         bgpPort = port;
320
321         if(bgpThriftClient == null) {
322             LOGGER.error("Failed to connect to BGP server since Bgp Thrift Client is not initialized yet.");
323             return;
324         }
325         try {
326             bgpThriftClient.connect(host, port);
327             LOGGER.debug("Connected to BGP server {} on port {} ", host, port);
328         } catch (BgpRouterException b) {
329             LOGGER.error("Failed to connect to BGP server " + host + " on port " + port + " due to BgpRouter Exception number " + b.getErrorCode());
330             LOGGER.debug("BgpRouterException trace ", b);
331             throw b;
332         } catch (TException t) {
333             LOGGER.error("Failed to initialize BGP Connection due to Transport error ");
334             throw t;
335         }
336         catch (Exception e) {
337             LOGGER.error("Failed to initialize BGP Connection ");
338             throw e;
339         }
340     }
341
342     public void configureBgp(long asNum, String routerId) {
343         try {
344             bgpConfiguration.setAsNum(asNum);
345             bgpConfiguration.setRouterId(routerId);
346         } catch(Exception e) {
347             LOGGER.error("failed configuring bgp ",e);
348         }
349     }
350
351     public synchronized void reInitConn() {
352
353         try {
354             bgpThriftClient.reInit();
355             LOGGER.debug("Reinitialized connection to BGP Server {}", bgpHost);
356         } catch (BgpRouterException b) {
357             LOGGER.error("Failed to reinitialize connection to BGP server {} on port {} due to BgpRouter Exception number {}", bgpHost, bgpPort, b.getErrorCode());
358             LOGGER.debug("BgpRouterException trace ", b);
359         } catch (TException t) {
360             LOGGER.error("Failed to reinitialize BGP Connection due to Transport error.");
361         }
362         catch (Exception e) {
363             LOGGER.error("Failed to reinitialize BGP Connection.", e);
364         }
365     }
366
367     public void disconnect() {
368         bgpThriftClient.disconnect();
369     }
370
371
372 }