Merge "MD SAL Util API exposed as a Service"
[vpnservice.git] / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / bgpmanager / BgpConfigurationManager.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 import java.util.Collections;
11 import java.util.Map;
12 import java.util.Set;
13
14 import org.apache.thrift.TException;
15 import org.opendaylight.bgpmanager.globals.BgpConfiguration;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yangtools.concepts.ListenerRegistration;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.BgpRouter;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.BgpNeighbors;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.BgpNeighbor;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.List;
32
33 import com.google.common.base.Optional;
34 import com.google.common.base.Preconditions;
35
36 public class BgpConfigurationManager {
37     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
38     private ListenerRegistration<DataChangeListener> listenerRegistration;
39     private BgpConfiguration bgpConfiguration;
40     private BgpManager bgpManager;
41     private final DataBroker broker;
42     private static final int MAX_RETRIES_BGP_COMMUNICATION = 1;
43     private enum BgpOp {
44         START_BGP, ADD_NGHBR, DEL_NGHBR
45     }
46
47     public BgpConfigurationManager(final DataBroker db, BgpConfiguration bgpCfg, BgpManager bgpMgr) {
48         broker = db;
49         bgpConfiguration = bgpCfg;
50         bgpManager = bgpMgr;
51         BgpRtrCfgManager rtrCfgManager = new BgpRtrCfgManager(broker);
52         BgpNghbrCfgManager nghbrCfgManager = new BgpNghbrCfgManager(broker);
53     }
54
55     public class BgpRtrCfgManager extends AbstractDataChangeListener<BgpRouter> implements AutoCloseable {
56
57         public BgpRtrCfgManager(final DataBroker db) {
58             super(BgpRouter.class);
59             registerListener(db);
60         }
61
62         private void registerListener(final DataBroker db) {
63             try {
64                 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
65                     getWildCardPath(), BgpRtrCfgManager.this, DataChangeScope.SUBTREE);
66             } catch (final Exception e) {
67                 LOG.error("BGP Configuration DataChange listener registration fail!", e);
68                 throw new IllegalStateException("BGP Configuration registration Listener failed.", e);
69             }
70         }
71
72         private synchronized void removeBgpRouter(BgpRouter del)
73         {
74             bgpManager.disconnect();
75
76             bgpConfiguration.setRouterId("");
77             bgpConfiguration.setAsNum(0);
78
79         }
80
81         @Override
82         protected void remove(InstanceIdentifier<BgpRouter> identifier,
83                               BgpRouter del) {
84
85             LOG.info("Bgp Router deleted in DS - " + "key: " + identifier + ", value=" + del);
86
87             removeBgpRouter(del);
88
89         }
90
91         private synchronized void updateBgpRouter(BgpRouter original, BgpRouter update)
92         {
93             if(bgpConfiguration.getAsNum() != update.getLocalAsNumber()) {
94                 bgpConfiguration.setAsNum(update.getLocalAsNumber());
95                 bgpConfiguration.setConfigUpdated();
96             }
97             if(bgpConfiguration.getRouterId() != update.getLocalAsIdentifier().getIpv4Address().getValue()) {
98                 bgpConfiguration.setRouterId(update.getLocalAsIdentifier().getIpv4Address().getValue());
99                 bgpConfiguration.setConfigUpdated();
100             }
101
102             if(bgpConfiguration.isConfigUpdated()) {
103                 configureBgpServer(BgpOp.START_BGP);
104                 bgpConfiguration.unsetConfigUpdated();
105             }
106
107         }
108
109         @Override
110         protected void update(InstanceIdentifier<BgpRouter> identifier,
111                               BgpRouter original, BgpRouter update) {
112
113             LOG.info("Bgp Router Updated in DS - " + "key: " + identifier + ", original=" + original + ", update=" + update);
114
115             updateBgpRouter(original, update);
116         }
117
118         private synchronized void addBgpRouter(BgpRouter value){
119             if(value.getLocalAsNumber() != null) {
120                 bgpConfiguration.setAsNum(value.getLocalAsNumber());
121             }
122             if(value.getLocalAsIdentifier() != null) {
123                 bgpConfiguration.setRouterId(value.getLocalAsIdentifier().getIpv4Address().getValue());
124             }
125
126             if(value.getLocalAsNumber() == null || value.getLocalAsIdentifier() == null)
127                 return;
128
129             configureBgpServer(BgpOp.START_BGP);
130         }
131
132         @Override
133         protected void add(InstanceIdentifier<BgpRouter> identifier,
134                            BgpRouter value) {
135             LOG.info("Bgp Router added in DS - " + "key: " + identifier + ", value=" + value);
136             LOG.info("Bgp Router localASNumber:" + value.getLocalAsNumber());
137             LOG.info("Bgp Router localASIdentifier:" + value.getLocalAsIdentifier());
138
139             addBgpRouter(value);
140         }
141
142         private InstanceIdentifier<BgpRouter> getWildCardPath() {
143             return InstanceIdentifier.create(BgpRouter.class);
144         }
145
146         @Override
147         public void close() throws Exception {
148             if (listenerRegistration != null) {
149                 try {
150                     listenerRegistration.close();
151                 } catch (final Exception e) {
152                     LOG.error("Error when cleaning up DataChangeListener.", e);
153                 }
154                 listenerRegistration = null;
155             }
156             LOG.info("Bgp Router Manager Closed");
157         }
158
159     }
160     public class BgpNghbrCfgManager extends AbstractDataChangeListener<BgpNeighbors> implements AutoCloseable {
161
162         public BgpNghbrCfgManager(final DataBroker db) {
163             super(BgpNeighbors.class);
164             registerListener(db);
165         }
166
167         private void registerListener(final DataBroker db) {
168             try {
169                 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
170                     getWildCardPath(), BgpNghbrCfgManager.this, DataChangeScope.SUBTREE);
171             } catch (final Exception e) {
172                 LOG.error("BGP Neighbor DataChange listener registration fail!", e);
173                 throw new IllegalStateException("BGP Neighbor registration Listener failed.", e);
174             }
175         }
176
177         private synchronized void removeBgpNeighbors(BgpNeighbors del) {
178             List<BgpNeighbor> bgpNeighborList = del.getBgpNeighbor();
179             BgpNeighbor gateway = bgpNeighborList.get(0);
180
181             if(gateway != null) {
182                 if ((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
183                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress) gateway.getPeerAddressType()).getIpAddress();
184                     LOG.info("Bgp Neighbor IP Address " + neighborIPAddr.getIpv4Address().getValue());
185
186                     configureBgpServer(BgpOp.DEL_NGHBR);
187
188                     bgpConfiguration.setNeighbourIp("");
189                     bgpConfiguration.setNeighbourAsNum(0);
190
191                 }
192             }
193
194         }
195
196         @Override
197         protected void remove(InstanceIdentifier<BgpNeighbors> identifier,
198                               BgpNeighbors del) {
199
200             LOG.info("Bgp Neighbors deleted in DS - " + "key: " + identifier + ", value=" + del);
201             removeBgpNeighbors(del);
202         }
203
204         private synchronized void updateBgpNeighbors(BgpNeighbors original, BgpNeighbors update) {
205
206             List<BgpNeighbor> bgpNeighborList = update.getBgpNeighbor();
207
208             //handle the case where there are no neighbors configured - single neighbor entry has been deleted
209             if(bgpNeighborList.isEmpty()) {
210                 configureBgpServer(BgpOp.DEL_NGHBR);
211                 return;
212             }
213
214             //We will always consider the first element of this list, since there can be just one DC Gateway
215             BgpNeighbor gateway = bgpNeighborList.get(0);
216
217             if(gateway != null) {
218                 if(gateway.getAsNumber() != null ||
219                     ((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress))) {
220                     //there is an updated neighbor, so we need to delete the old neighbor
221                     configureBgpServer(BgpOp.DEL_NGHBR);
222                 }
223                 if(gateway.getAsNumber() != null) {
224                     LOG.info("Bgp Neighbor AS number " + gateway.getAsNumber());
225                     if(bgpConfiguration.getNeighbourAsNum() != gateway.getAsNumber()) {
226                         bgpConfiguration.setNeighbourAsNum(gateway.getAsNumber());
227                         bgpConfiguration.setConfigUpdated();
228                     }
229                 }
230                 if((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
231                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)gateway.getPeerAddressType()).getIpAddress();
232                     LOG.info("Bgp Neighbor IP Address " + neighborIPAddr.getIpv4Address().getValue());
233                     if(bgpConfiguration.getNeighbourIp() != neighborIPAddr.getIpv4Address().getValue()) {
234                         bgpConfiguration.setNeighbourIp(neighborIPAddr.getIpv4Address().getValue());
235                         bgpConfiguration.setConfigUpdated();
236                     }
237
238                 }
239             }
240             if(bgpConfiguration.isConfigUpdated()) {
241                 //add the newly configured neighbor
242                 configureBgpServer(BgpOp.ADD_NGHBR);
243             }
244         }
245
246         @Override
247         protected void update(InstanceIdentifier<BgpNeighbors> identifier,
248                               BgpNeighbors original, BgpNeighbors update) {
249
250             LOG.info("Bgp Neighbors Updated in DS - " + "key: " + identifier + ", original=" + original + ", update=" + update);
251
252             updateBgpNeighbors(original, update);
253
254         }
255
256         private synchronized void addBgpNeighbors(BgpNeighbors value) {
257             List<BgpNeighbor> bgpNeighborList = value.getBgpNeighbor();
258
259             //We will always consider the first element of this list, since there can be just one DC Gateway
260             BgpNeighbor gateway = bgpNeighborList.get(0);
261
262             if(gateway != null) {
263                 if(gateway.getAsNumber() != null) {
264                     LOG.info("Bgp Neighbor AS number " + gateway.getAsNumber());
265                     bgpConfiguration.setNeighbourAsNum(gateway.getAsNumber());
266                 }
267                 if((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
268                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)gateway.getPeerAddressType()).getIpAddress();
269                     LOG.info("Bgp Neighbor IP Address " + neighborIPAddr.getIpv4Address().getValue());
270                     bgpConfiguration.setNeighbourIp(neighborIPAddr.getIpv4Address().getValue());
271
272                 }
273                 if(bgpConfiguration.getNeighbourAsNum() != 0  && bgpConfiguration.getNeighbourIp() != null) {
274                     configureBgpServer(BgpOp.ADD_NGHBR);
275                 }
276             }
277
278         }
279
280         @Override
281         protected void add(InstanceIdentifier<BgpNeighbors> identifier,
282                            BgpNeighbors value) {
283             LOG.info("key: " + identifier + ", value=" + value);
284             LOG.info("Bgp Neighbor added in DS - " + "key: " + identifier + ", value=" + value);
285
286             addBgpNeighbors(value);
287         }
288
289         private InstanceIdentifier<?> getWildCardPath() {
290             return InstanceIdentifier.create(BgpNeighbors.class);
291         }
292
293
294         @Override
295         public void close() throws Exception {
296             if (listenerRegistration != null) {
297                 try {
298                     listenerRegistration.close();
299                 } catch (final Exception e) {
300                     LOG.error("Error when cleaning up DataChangeListener.", e);
301                 }
302                 listenerRegistration = null;
303             }
304             LOG.info("Bgp Neighbor Manager Closed");
305         }
306
307     }
308
309     private void configureBgpServer(BgpOp bgpOp) {
310         int retryCount = 0;
311         boolean retry = false;
312         do {
313             try {
314                 switch(bgpOp) {
315                     case START_BGP:
316                         bgpManager.startBgpService();
317                         break;
318                     case ADD_NGHBR:
319                         bgpManager.addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
320                         break;
321                     case DEL_NGHBR:
322                         bgpManager.deleteNeighbor(bgpConfiguration.getNeighbourIp());
323                         break;
324                     default:
325                         LOG.info("Invalid configuration option");
326                 }
327
328                 retry = false;
329             } catch (TException t) {
330                 retry = true;
331                 retryCount++;
332             }
333         } while(retry && retryCount <= MAX_RETRIES_BGP_COMMUNICATION);
334     }
335 }