Bump ODL dependencies to Fluorine (HONEYCOMB-433)
[honeycomb.git] / infra / northbound / bgp / src / main / java / io / fd / honeycomb / infra / bgp / neighbors / NeighborCustomizer.java
1 /*
2  * Copyright (c) 2017 Cisco and/or its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package io.fd.honeycomb.infra.bgp.neighbors;
18
19 import static com.google.common.base.Preconditions.checkNotNull;
20 import static com.google.common.base.Preconditions.checkState;
21
22 import com.google.common.annotations.VisibleForTesting;
23 import io.fd.honeycomb.infra.bgp.BgpConfiguration;
24 import io.fd.honeycomb.translate.spi.write.ListWriterCustomizer;
25 import io.fd.honeycomb.translate.write.WriteContext;
26 import io.fd.honeycomb.translate.write.WriteFailedException;
27 import java.util.HashMap;
28 import java.util.Map;
29 import javax.annotation.Nonnull;
30 import javax.annotation.concurrent.GuardedBy;
31 import javax.annotation.concurrent.ThreadSafe;
32 import org.opendaylight.protocol.bgp.openconfig.spi.BGPTableTypeRegistryConsumer;
33 import org.opendaylight.protocol.bgp.rib.impl.config.AppPeer;
34 import org.opendaylight.protocol.bgp.rib.impl.config.BgpPeer;
35 import org.opendaylight.protocol.bgp.rib.impl.config.PeerBean;
36 import org.opendaylight.protocol.bgp.rib.impl.config.PeerGroupConfigLoader;
37 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
38 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Config;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
41 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.NeighborKey;
42 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
43 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.NetworkInstances;
44 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.NetworkInstance;
45 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.Protocols;
46 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.network.instance.protocols.Protocol;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NeighborPeerGroupConfig;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev180329.NetworkInstanceProtocol;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 /**
54  * Writer responsible for management of BGP Neighbors. Partially based on BgpDeployerImpl from ODL's BGP (was hard to
55  * use directly due to OSGI dependencies).
56  */
57 @ThreadSafe
58 final class NeighborCustomizer implements ListWriterCustomizer<Neighbor, NeighborKey> {
59     private static final Logger LOG = LoggerFactory.getLogger(NeighborCustomizer.class);
60     private final RIB globalRib;
61     private final BGPPeerRegistry peerRegistry;
62     private final PeerGroupConfigLoader peerGroupLoader;
63     private BGPTableTypeRegistryConsumer tableTypeRegistry;
64     @VisibleForTesting
65     static final InstanceIdentifier<Bgp> bgpIid = InstanceIdentifier.create(NetworkInstances.class)
66             .child(NetworkInstance.class).child(Protocols.class).child(Protocol.class).augmentation(
67                     NetworkInstanceProtocol.class).child(Bgp.class);
68
69
70     @GuardedBy("this")
71     private final Map<InstanceIdentifier<Neighbor>, PeerBean> peers = new HashMap<>();
72
73     public NeighborCustomizer(@Nonnull final RIB globalRib, @Nonnull final BGPPeerRegistry peerRegistry,
74                               @Nonnull final BGPTableTypeRegistryConsumer tableTypeRegistry,
75                               final BgpConfiguration configuration) {
76         this.globalRib = checkNotNull(globalRib, "globalRib should not be null");
77         this.peerRegistry = checkNotNull(peerRegistry, "peerRegistry should not be null");
78         this.tableTypeRegistry = checkNotNull(tableTypeRegistry, "tableTypeRegistry should not be null");
79         this.peerGroupLoader = checkNotNull(configuration, "configuration should not be null");
80     }
81
82     @VisibleForTesting
83     synchronized void addPeer(@Nonnull final InstanceIdentifier<Neighbor> id,
84                               @Nonnull final PeerBean peer) {
85         peers.put(id, peer);
86     }
87
88     @VisibleForTesting
89     synchronized boolean isPeerConfigured(@Nonnull final InstanceIdentifier<Neighbor> id) {
90         return peers.containsKey(id);
91     }
92
93     @Override
94     public synchronized void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Neighbor> id,
95                                                     @Nonnull final Neighbor neighbor,
96                                                     @Nonnull final WriteContext writeContext)
97         throws WriteFailedException {
98         final PeerBean peer;
99         if (isAppPeer(neighbor)) {
100             LOG.debug("Creating AppPeer bean for {}: {}", id, neighbor);
101             peer = new AppPeer();
102         } else {
103             LOG.debug("Starting BgpPeer bean for {}: {}", id, neighbor);
104             peer = new BgpPeer(null);
105         }
106         LOG.debug("Starting bgp peer for {}", id);
107         peer.start(globalRib, neighbor, bgpIid, peerGroupLoader, tableTypeRegistry);
108         peer.instantiateServiceInstance();
109         addPeer(id, peer);
110     }
111
112     static boolean isAppPeer(final Neighbor neighbor) {
113         Config config = neighbor.getConfig();
114         if (config != null) {
115             NeighborPeerGroupConfig config1 = config.augmentation(NeighborPeerGroupConfig.class);
116             if (config1 != null) {
117                 String peerGroup = config1.getPeerGroup();
118                 return peerGroup != null && peerGroup.equals("application-peers");
119             }
120         }
121         return false;
122     }
123
124     @Override
125     public synchronized void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Neighbor> id,
126                                                      @Nonnull final Neighbor dataBefore,
127                                                      @Nonnull final Neighbor dataAfter,
128                                                      @Nonnull final WriteContext writeContext)
129         throws WriteFailedException {
130         LOG.debug("Updating Peer instance {} with configuration: {}", id, dataAfter);
131         final PeerBean peer = peers.get(id);
132         checkState(peer != null, "Could not find peer bean while updating neighbor {}", id);
133         closePeerBean(peer);
134         peer.start(globalRib, dataAfter, bgpIid, peerGroupLoader, tableTypeRegistry);
135         peer.instantiateServiceInstance();
136         LOG.debug("Peer instance updated {}", peer);
137     }
138
139     @Override
140     public synchronized void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Neighbor> id,
141                                                      @Nonnull final Neighbor dataBefore,
142                                                      @Nonnull final WriteContext writeContext)
143         throws WriteFailedException {
144         LOG.debug("Removing Peer instance: {}", id);
145         final PeerBean peer = peers.remove(id);
146         if (peer != null) {
147             closePeerBean(peer);
148             LOG.debug("Peer instance removed {}", peer);
149         }
150     }
151
152     private static void closePeerBean(final PeerBean peer) {
153         try {
154             peer.closeServiceInstance().get();
155         } catch (final Exception e) {
156             LOG.error("Peer instance failed to close service instance", e);
157         }
158         peer.close();
159     }
160 }