Merge "Updating operational datastore"
[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.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 public class BgpManager implements BindingAwareProvider, AutoCloseable, IBgpManager {
34
35     private static final Logger s_logger = LoggerFactory.getLogger(BgpManager.class);
36     private BgpConfigurationManager bgpConfigurationMgr;
37     private BgpConfiguration    bgpConfiguration = new BgpConfiguration();
38     private BgpRouter           bgpThriftClient;
39     private BgpThriftService    bgpThriftService;
40     private String                              bgpHost;
41     private int                                 bgpPort;
42
43     private void initializeBGPCommunication() {
44         //start our side of thrift server
45         bgpThriftService = new BgpThriftService();
46         bgpThriftService.start();
47
48         //start bgp thrift client connection
49         bgpThriftClient = new BgpRouter();
50
51         //get bgp server, port from config.ini and connect
52         bgpHost = System.getProperty(BgpConstants.BGP_SPEAKER_HOST_NAME, BgpConstants.DEFAULT_BGP_HOST_NAME);
53         bgpPort = Integer.getInteger(BgpConstants.BGP_SPEAKER_THRIFT_PORT, BgpConstants.DEFAULT_BGP_THRIFT_PORT);
54
55         configureBgpServer(bgpHost, bgpPort);
56         try {
57             connectToServer(bgpHost, bgpPort);
58         } catch (Exception e) {
59             //nothing to be done here, the logs have already been printed by the Exception handlers of "connectToServer"
60         }
61         /*  read bgp router and peer info from DS
62             for the case when the BGP module came down but the DataStore was still up
63         */
64         //for testing
65         configureBgp(101, "10.10.10.10");
66
67         // Now try start bgp - if bgp is already Active, it will tell us, nothing to do then
68         try {
69             bgpThriftClient.startBgp((int)bgpConfiguration.getAsNum(), bgpConfiguration.getRouterId());
70             s_logger.info("Started BGP with AS number " + (int)bgpConfiguration.getAsNum() + " and router id " + bgpConfiguration.getRouterId());
71         } catch (BgpRouterException be) {
72             if(be.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
73                 s_logger.info("bgp server already active");
74                 return;
75             }
76             else {
77                 s_logger.error("application error while starting bgp server " + be.getErrorCode());
78                 return;
79             }
80
81         }  catch (TException t) {
82             s_logger.error("Transport error while starting bgp server ", t);
83             return;
84         } catch (Exception e) {
85             s_logger.error("Error while starting bgp server", e);
86         }
87
88         //For testing - remove later
89         addNeighbor("169.144.42.168", 102);
90
91     }
92
93     @Override
94     public void onSessionInitiated(ProviderContext session) {
95         s_logger.info("BgpManager Session Initiated");
96         try {
97             final DataBroker dataBroker = session.getSALService(DataBroker.class);
98             bgpConfigurationMgr = new BgpConfigurationManager(dataBroker);
99         } catch (Exception e) {
100             s_logger.error("Error initializing services", e);
101         }
102
103         initializeBGPCommunication();
104     }
105
106
107    @Override
108     public void close() throws Exception {
109         s_logger.info("BgpManager Closed");
110     }
111
112     private void setBgpServerDetails() {
113         if(bgpThriftClient != null)
114             bgpThriftClient.setBgpServer(bgpHost, bgpPort);
115     }
116
117     private void configureBgpServer(String bgpServer, int bgpPort) {
118         bgpConfiguration.setBgpServer(bgpServer);
119         bgpConfiguration.setBgpPort(bgpPort);
120         setBgpServerDetails();
121     }
122
123     private void addNeighbor(String ipAddress, int asNum) {
124         if(bgpThriftClient == null) {
125             s_logger.info("Add BGP Neighbor - bgpThriftClient is null. Unable to add BGP Neighbor.");
126             return;
127         }
128         bgpConfiguration.setNeighbourIp(ipAddress);
129         bgpConfiguration.setNeighbourAsNum(asNum);
130         //updateBgpConfiguration(bgpConfiguration);
131         try {
132             bgpThriftClient.addNeighbor(ipAddress, asNum);
133         } catch (BgpRouterException b) {
134             s_logger.error("Failed to add BGP neighbor " + ipAddress + "due to BgpRouter Exception number " + b.getErrorCode());
135             s_logger.error("BgpRouterException trace ", b);
136         } catch (TException t) {
137             s_logger.error(String.format("Failed adding neighbor %s due to Transport error", ipAddress));
138             reInitConn();
139         } catch (Exception e) {
140             s_logger.error(String.format("Failed adding neighbor %s", ipAddress));
141         }
142     }
143
144
145     private void deleteNeighbor(String ipAddress) {
146         if(bgpThriftClient == null) {
147             s_logger.info("Delete BGP Neighbor - bgpThriftClient is null. Unable to delete BGP Neighbor.");
148             return;
149         }
150         bgpConfiguration.setNeighbourIp("");
151         try {
152             bgpThriftClient.delNeighbor(ipAddress);
153         } catch (BgpRouterException b) {
154             s_logger.error("Failed to delete BGP neighbor " + ipAddress + "due to BgpRouter Exception number " + b.getErrorCode());
155             s_logger.error("BgpRouterException trace ", b);
156         }catch (TException t) {
157             s_logger.error(String.format("Failed deleting neighbor %s due to Transport error", ipAddress));
158             reInitConn();
159         } catch (Exception e) {
160             s_logger.error(String.format("Failed deleting neighbor %s", ipAddress));
161         }
162     }
163
164
165     @Override
166     public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts) {
167         if(bgpThriftClient == null) {
168             s_logger.info("Add BGP vrf - bgpThriftClient is null. Unable to add BGP vrf.");
169             return;
170         }
171         try {
172             bgpThriftClient.addVrf(rd, new ArrayList<>(importRts), new ArrayList<>(exportRts));
173         } catch (BgpRouterException b) {
174             s_logger.error("Failed to add BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
175             s_logger.error("BgpRouterException trace ", b);
176         } catch (TException t) {
177             s_logger.error(String.format("Failed adding vrf %s due to Transport error", rd));
178             reInitConn();
179         } catch (Exception e) {
180             s_logger.error(String.format("Failed adding vrf %s", rd));
181         }
182     }
183
184     @Override
185     public void deleteVrf(String rd) {
186         if(bgpThriftClient == null) {
187             s_logger.info("Delete BGP vrf - bgpThriftClient is null. Unable to delete BGP vrf.");
188             return;
189         }
190         try {
191             bgpThriftClient.delVrf(rd);
192         } catch (BgpRouterException b) {
193             s_logger.error("Failed to delete BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
194             s_logger.error("BgpRouterException trace ", b);
195         } catch (TException t) {
196             s_logger.error(String.format("Failed deleting vrf %s due to Transport error", rd));
197             reInitConn();
198         } catch (Exception e) {
199             s_logger.error(String.format("Failed deleting vrf %s", rd));
200         }
201     }
202
203     @Override
204     public void addPrefix(String rd, String prefix, String nextHop, int vpnLabel) {
205         if(bgpThriftClient == null) {
206             s_logger.info("Add BGP prefix - bgpThriftClient is null. Unable to add BGP prefix.");
207             return;
208         }
209         try {
210             bgpThriftClient.addPrefix(rd, prefix, nextHop, vpnLabel);
211         } catch (BgpRouterException b) {
212             s_logger.error("Failed to add BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
213             s_logger.error("BgpRouterException trace ", b);
214         } catch (TException t) {
215             s_logger.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d due to Transport error",
216                 rd, prefix, nextHop, vpnLabel));
217             reInitConn();
218         } catch (Exception e) {
219             s_logger.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d",
220                 rd, prefix, nextHop, vpnLabel));
221         }
222     }
223
224
225     @Override
226     public void deletePrefix(String rd, String prefix) {
227         if(bgpThriftClient == null) {
228             s_logger.info("Delete BGP prefix - bgpThriftClient is null. Unable to delete BGP prefix.");
229             return;
230         }
231         try {
232             bgpThriftClient.delPrefix(rd, prefix);
233         } catch (BgpRouterException b) {
234             s_logger.error("Failed to delete BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
235             s_logger.error("BgpRouterException trace ", b);
236         } catch (TException t) {
237             s_logger.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s due to Transport error",
238                 rd, prefix));
239             reInitConn();
240         } catch (Exception e) {
241             s_logger.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s",
242                 rd, prefix));
243         }
244     }
245
246     private void connectToServer(String host, int port) throws Exception {
247
248         bgpHost = host;
249         bgpPort = port;
250
251         if(bgpThriftClient == null) {
252             s_logger.error("Failed to connect to BGP server since Bgp Thrift Client is not initialized yet.");
253             return;
254         }
255         try {
256             bgpThriftClient.connect(host, port);
257             s_logger.info("Connected to BGP server " + host + " on port " + port);
258         } catch (BgpRouterException b) {
259             s_logger.error("Failed to connect to BGP server " + host + " on port " + port + " due to BgpRouter Exception number " + b.getErrorCode());
260             s_logger.error("BgpRouterException trace ", b);
261             throw b;
262         } catch (TException t) {
263             s_logger.error("Failed to initialize BGP Connection due to Transport error ", t);
264             throw t;
265         }
266         catch (Exception e) {
267             s_logger.error("Failed to initialize BGP Connection ", e);
268             throw e;
269         }
270     }
271
272     public void configureBgp(long asNum, String routerId) {
273         try {
274             bgpConfiguration.setAsNum(asNum);
275             bgpConfiguration.setRouterId(routerId);
276         } catch(Throwable e) {
277             s_logger.error("failed configuring bgp ",e);
278         }
279     }
280
281     public void reInitConn() {
282
283         try {
284             bgpThriftClient.reInit();
285             s_logger.info("Reinitialized connection to BGP Server " + bgpHost);
286         } catch (BgpRouterException b) {
287             s_logger.error("Failed to reinitialize connection to BGP server " + bgpHost + " on port " + bgpPort + " due to BgpRouter Exception number " + b.getErrorCode());
288             s_logger.error("BgpRouterException trace ", b);
289         } catch (TException t) {
290             s_logger.error("Failed to reinitialize BGP Connection due to Transport error.", t);
291         }
292         catch (Exception e) {
293             s_logger.error("Failed to reinitialize BGP Connection.", e);
294         }
295     }
296
297     /*public synchronized void startBgpSync() {
298         boolean getRoutes = true;
299         readBgpConfiguration();
300         try {
301             pushConfigurationToBgp();
302
303         } catch (BgpRouterException b) {
304             s_logger.error("Failed to push configuration to BGP due to BgpRouter Exception number " + b.getErrorCode());
305             s_logger.error("BgpRouterException trace ", b);
306             if(b.getErrorCode() == BgpRouterException.BGP_ERR_INACTIVE)
307                 getRoutes = false;
308         } catch (Exception e) {
309             s_logger.error("Failed to push configuration to bgp ", e);
310         }
311         if(getRoutes == true)
312             pullConfigurationFromBgp();
313         //controllerResyncLatch.countDown();
314     }*/
315
316     /*public void waitForControllerBgpResync() {
317         try {
318             controllerResyncLatch.await();
319         } catch (InterruptedException e) {
320         }
321     }*/
322
323     /*private void pullConfigurationFromBgp() {
324         //get routes from bgp server
325         s_logger.info("Starting bgp route sync");
326         try {
327             bgpThriftClient.doRouteSync();
328         } catch (BgpRouterException b) {
329             s_logger.error("Failed BGP Route sync due to BgpRouter Exception number " + b.getErrorCode());
330             s_logger.error("BgpRouterException trace ", b);
331         } catch (Exception e) {
332             s_logger.error("Failed to pull configuration from bgp ", e);
333         }
334     }*/
335
336     /*private BgpConfiguration readBgpConfiguration() {
337         if (cache != null) {
338             bgpConfiguration = cache.get("bgpConfiguration");
339             if (bgpConfiguration == null) {
340                 s_logger.info("Created bgp configuration cache");
341                 bgpConfiguration = new BgpConfiguration();
342                 cache.put("bgpConfiguration", bgpConfiguration);
343             } else {
344                 s_logger.info("Using bgp configuration cache");
345             }
346         }
347         return bgpConfiguration;
348     }*/
349
350     /*public synchronized void pushConfigurationToBgp() throws Exception {
351         if (bgpConfiguration.getAsNum() == 0) {
352             s_logger.error("No as num configured, Skipping the push configuration to bgp ");
353             throw new BgpRouterException(BgpRouterException.BGP_ERR_INACTIVE);
354             //return;
355         }
356         if(bgpThriftClient == null) {
357             s_logger.error("bgpThriftClient is null. Skipping the push configuration to bgp.");
358             throw new BgpRouterException(BgpRouterException.BGP_ERR_INACTIVE);
359             //return;
360         }
361
362         try {
363             bgpThriftClient.startBgp((int)bgpConfiguration.getAsNum(), bgpConfiguration.getRouterId());
364             s_logger.info("Started BGP with AS number " + (int)bgpConfiguration.getAsNum() + " and router id " + bgpConfiguration.getRouterId());
365         } catch (BgpRouterException be) {
366             if(be.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
367                 s_logger.info("bgp server already active");
368                 return;         //the assumption here is that bgp server is configured already with neighbor, vrfs and routes as well
369             } if(be.getErrorCode() == BgpRouterException.BGP_ERR_INACTIVE) {
370                 s_logger.info("bgp server inactive");
371                 throw be;
372             }
373
374             else {
375                 s_logger.error("application error while starting bgp server %d", be.getErrorCode());
376                 return;
377             }
378
379         } catch (SocketTimeoutException to) {
380             s_logger.error("Socket Timeout error while starting bgp server", to);
381             return;
382         } catch (TException t) {
383             s_logger.error("Transport error while starting bgp server ", t);
384             return;
385         } catch (Exception e) {
386             s_logger.error("Error while starting bgp server", e);
387         }
388
389         if (bgpConfiguration.getNeighbourIp().trim().length() > 0) {
390             try {
391                 bgpThriftClient.addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
392             } catch (TException t) {
393                 s_logger.error("Failed to push vrf to bgp due to Transport error" );
394                 //retry connection
395                 reInitConn();
396                 addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
397             } catch (Exception e) {
398                 s_logger.error("Error while starting bgp server", e);
399             }
400         }
401
402         Tenant tenant;
403         try {
404             tenant = tenantManager.getTenant("NEUTRON");
405         } catch (TenantNotFoundException e) {
406             s_logger.error("Tenant not found. Skipping push configuration to bgp.");
407             return;
408         }
409         if (tenant != null) {
410             int tenantId = tenant.getTenantId();
411
412             Set<VpnInstanceInfo> vpnInfos = l3Manager.getVpnInstanceManager().getVpnsForTenant(tenantId);
413             s_logger.info("Number of vpns to configure is "+vpnInfos.size());
414             for (VpnInstanceInfo vpnInfo: vpnInfos) {
415                 try {
416                     bgpThriftClient.addVrf(vpnInfo.getRouteDistinguisher(),
417                         new ArrayList<>(vpnInfo.getRtImportList()),
418                         new ArrayList<>(vpnInfo.getRtExportList()));
419                 } catch (TException t) {
420                     s_logger.error("Failed to push vrf to bgp due to Transport error" );
421                     //retry connection
422                     reInitConn();
423                     addVrf(vpnInfo.getRouteDistinguisher(), new ArrayList<>(vpnInfo.getRtImportList()),
424                         new ArrayList<>(vpnInfo.getRtExportList()));
425                 } catch (Exception e) {
426                     s_logger.error("Failed to push vrf to bgp ", e);
427                 }
428             }
429             for (VpnInstanceInfo vpnInfo: vpnInfos) {
430                 ConcurrentMap<FibInfo, Object>  fibInfos = l3Manager.getVpnInstanceManager().
431                     getLocalFibInfosForRdCache(vpnInfo.getRouteDistinguisher());
432                 s_logger.info("Number of fib infos to configure is "+fibInfos.size());
433                 for (FibInfo fibInfo : fibInfos.keySet()) {
434                     try {
435                         bgpThriftClient.addPrefix(vpnInfo.getRouteDistinguisher(), fibInfo.getDestinationPrefix(),
436                             fibInfo.getNextHopPrefix(), (int) fibInfo.getLabel());
437                     } catch (TException t) {
438                         s_logger.error("Failed to push route to bgp due to Transport error" );
439                         reInitConn();
440                         addPrefix(vpnInfo.getRouteDistinguisher(), fibInfo.getDestinationPrefix(),
441                             fibInfo.getNextHopPrefix(), (int) fibInfo.getLabel());
442                     } catch (Exception e) {
443                         s_logger.error("Failed to push route to bgp ", e);
444                     }
445                 }
446             }
447         }
448
449     }
450     */
451
452 /*    public void disconnect() {
453         bgpThriftClient.disconnect();
454     }
455
456     public void setRoute(Route r) {
457         s_logger.info("Setting route in VPN Manager");
458         //l3Manager.getVpnInstanceManager().addRoute(r.getRd(), r.getPrefix(), r.getNexthop(), r.getLabel());
459     }*/
460
461     /* For testing purposes */
462     /*public String ribGet() {
463         String family = "ipv4";
464         String format = "json";
465
466         try {
467             List<Route> routeList = bgpThriftClient.getRoutes();
468             Iterator<Route> iter = routeList.iterator();
469             while(iter.hasNext()) {
470                 Route r = iter.next();
471                 System.out.println("Route:: vrf:" + r.getRd() + " Prefix: " + r.getPrefix() + " Nexthop: " + r.getNexthop() + "Label: " + r.getLabel());
472             }
473         } catch (Exception e) {
474             s_logger.error("Failed getting bgp routes ", e);
475         }
476         return null;
477     }*/
478
479
480 }