BUG-5685: Register BGP Peer Cluster Singleton Service 98/44098/1
authorClaudio D. Gasparini <cgaspari@cisco.com>
Wed, 10 Aug 2016 12:51:42 +0000 (14:51 +0200)
committerMilos Fabian <milfabia@cisco.com>
Tue, 16 Aug 2016 19:35:06 +0000 (19:35 +0000)
Register BGP Peer Cluster Singleton Service.
When running on clustering, it was need it to have
different configuration per instance to avoid conflicts.
Now all instance can have same configuration,
since cluster service provider take cares of make active
the one is running on Leader Cluster. If Leader goes down,
the instance from the new Leader will become active.

Change-Id: Ia4a95123e50fcb962c217b21967acf5a8820727d
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
(cherry picked from commit 259daaeb2ad7ebf70308abc0a098ab2ba096b375)

13 files changed:
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java
bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerImpl.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java
bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BgpDeployer.java
bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java
bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java
bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java

index 91ceb1864b351d3c3e3a884fdc2335cc19fe3983..1f33da993ccf7eab078fcbfae558583965ec2754 100755 (executable)
@@ -38,6 +38,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.openconfig.extensions.rev160614.Protocol1;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.PeerRole;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.osgi.framework.BundleContext;
 
@@ -85,18 +86,19 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        final RIB r = getRibDependency();
-        final WaitingServiceTracker<BgpDeployer> bgpDeployerTracker =
-                WaitingServiceTracker.create(BgpDeployer.class, this.bundleContext);
+        final RIB rib = getRibDependency();
+        final WaitingServiceTracker<BgpDeployer> bgpDeployerTracker = WaitingServiceTracker.create(BgpDeployer.class, this.bundleContext);
         final BgpDeployer bgpDeployer = bgpDeployerTracker.waitForService(WaitingServiceTracker.FIVE_MINUTES);
         //map configuration to OpenConfig BGP
         final Neighbor neighbor = bgpDeployer.getMappingService().fromBgpPeer(getAddPathDependency(), getAdvertizedTableDependency(), getHoldtimer(),
                 getHost(), getInitiateConnection(), getPassword(), getPort(), getRetrytimer(), getRemoteAs(), getPeerRole(), getSimpleRoutingPolicy());
         //write to configuration DS
-        final KeyedInstanceIdentifier<Neighbor, NeighborKey> neighborIId = bgpDeployer.getInstanceIdentifier().child(Protocols.class).child(Protocol.class,
-                new ProtocolKey(BGP.class, r.getInstanceIdentifier().getKey().getId().getValue()))
-                .augmentation(Protocol1.class).child(Bgp.class).child(Neighbors.class).child(Neighbor.class, neighbor.getKey());
-        bgpDeployer.writeConfiguration(neighbor, neighborIId);
+        final KeyedInstanceIdentifier<Protocol, ProtocolKey> protocolIId = bgpDeployer.getInstanceIdentifier().child(Protocols.class)
+            .child(Protocol.class, new ProtocolKey(BGP.class, rib.getInstanceIdentifier().getKey().getId().getValue()));
+        final InstanceIdentifier<Bgp> bgpIID = protocolIId.augmentation(Protocol1.class).child(Bgp.class);
+        final KeyedInstanceIdentifier<Neighbor, NeighborKey> neighborIId = protocolIId.augmentation(Protocol1.class).child(Bgp.class)
+            .child(Neighbors.class).child(Neighbor.class, neighbor.getKey());
+        bgpDeployer.onNeighborModified(bgpIID, neighbor, () -> bgpDeployer.writeConfiguration(neighbor, neighborIId));
         //get rib instance service, use filter
         final WaitingServiceTracker<BGPPeerRuntimeMXBean> peerTracker = WaitingServiceTracker.create(BGPPeerRuntimeMXBean.class,
                 this.bundleContext, "(" + InstanceType.PEER.getBeanName() + "=" + Ipv4Util.toStringIP(getHost()) + ")");
@@ -106,6 +108,7 @@ public final class BGPPeerModule extends org.opendaylight.controller.config.yang
             @Override
             protected Object handleInvocation(final Object proxy, final Method method, final Object[] args) throws Throwable {
                 if (method.getName().equals("close")) {
+                    bgpDeployer.onNeighborRemoved(bgpIID, neighbor);
                     runtimeRegistration.close();
                     bgpDeployerTracker.close();
                     peerTracker.close();
index d6f6cfa8b64db45564b2525b7bd19bb003fd185a..1f8d2cfc63d478d93ca9d6fadb675dfa70b3a6c7 100755 (executable)
@@ -85,7 +85,7 @@ public final class RIBImplModule extends org.opendaylight.controller.config.yang
         final KeyedInstanceIdentifier<Protocol, ProtocolKey> protocolIId = bgpDeployer.getInstanceIdentifier().child(Protocols.class)
             .child(Protocol.class, protocol.getKey());
         final InstanceIdentifier<Bgp> bgpIID = protocolIId.augmentation(Protocol1.class).child(Bgp.class);
-        bgpDeployer.onGlobalCreated(bgpIID, global, () -> bgpDeployer.writeConfiguration(protocol, protocolIId));
+        bgpDeployer.onGlobalModified(bgpIID, global, () -> bgpDeployer.writeConfiguration(protocol, protocolIId));
 
         //get rib instance service, use filter
         final WaitingServiceTracker<RIB> ribTracker = WaitingServiceTracker.create(RIB.class,
index 731b7a5a5118b2ad98536468d4aca2eab51121fc..ad269b6dea7708c8d28a3dc5718460aaae4ff251 100644 (file)
@@ -120,19 +120,22 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
         this.simpleRoutingPolicy = Optional.ofNullable(peerStatus);
         this.rib = Preconditions.checkNotNull(rib);
         this.name = name;
-        this.chain = rib.createPeerChain(this);
-        this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
         this.rpcRegistry = rpcRegistry;
         this.peerStats = new BGPPeerStatsImpl(this.name, this.tables);
 
         // add current peer to "configured BGP peer" stats
         this.rib.getRenderStats().getConfiguredPeerCounter().increaseCount();
+        this.chain = rib.createPeerChain(this);
     }
 
     public BGPPeer(final String name, final RIB rib, final PeerRole role, final RpcProviderRegistry rpcRegistry) {
         this(name, rib, role, null, rpcRegistry);
     }
 
+    public void instantiateServiceInstance() {
+        this.ribWriter = AdjRibInWriter.create(rib.getYangRibId(), this.peerRole, this.simpleRoutingPolicy, this.chain);
+    }
+
     @Override
     public synchronized void close() {
         releaseConnection();
@@ -337,14 +340,14 @@ public class BGPPeer implements BGPSessionListener, Peer, AutoCloseable, BGPPeer
 
     private synchronized void cleanup() {
         // FIXME: BUG-196: support graceful
-        for (final AdjRibOutListener adjRibOutListener : this.adjRibOutListenerSet.values()) {
-            adjRibOutListener.close();
-        }
+        this.adjRibOutListenerSet.values().forEach(AdjRibOutListener::close);
         this.adjRibOutListenerSet.clear();
         if (this.effRibInWriter != null) {
             this.effRibInWriter.close();
         }
-        this.ribWriter.removePeer();
+        if(this.ribWriter != null) {
+            this.ribWriter.removePeer();
+        }
         this.tables.clear();
     }
 
index 9d708d0ec732c2e7ae175bf0141be7873e9e4850..cb8def72e9aa3dd6ab632ddd45837f8d3c704abb 100755 (executable)
@@ -209,6 +209,7 @@ public final class RIBImpl extends DefaultRibReference implements ClusterSinglet
 
     @Override
     public synchronized void close() throws Exception {
+        this.domChain.close();
         if (registration != null) {
             registration.close();
             registration = null;
@@ -352,14 +353,7 @@ public final class RIBImpl extends DefaultRibReference implements ClusterSinglet
 
     @Override
     public ListenableFuture<Void> closeServiceInstance() {
-        try {
-            final DOMDataWriteTransaction t = this.domChain.newWriteOnlyTransaction();
-            t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId());
-            t.submit().checkedGet();
-        } catch (final TransactionCommitFailedException e) {
-            LOG.warn("Failed to remove RIB instance {} from DS.", getYangRibId(), e);
-        }
-        this.domChain.close();
+        LOG.info("Close RIB Singleton Service {}", this.getIdentifier());
         for (final LocRibWriter locRib : this.locRibs) {
             try {
                 locRib.close();
@@ -367,7 +361,13 @@ public final class RIBImpl extends DefaultRibReference implements ClusterSinglet
                 LOG.warn("Could not close LocalRib reference: {}", locRib, e);
             }
         }
-
+        try {
+            final DOMDataWriteTransaction t = this.domChain.newWriteOnlyTransaction();
+            t.delete(LogicalDatastoreType.OPERATIONAL, getYangRibId());
+            t.submit().checkedGet();
+        } catch (final TransactionCommitFailedException e) {
+            LOG.warn("Failed to remove RIB instance {} from DS.", getYangRibId(), e);
+        }
         this.renderStats.getLocRibRouteCounter().resetAll();
 
         if (this.configModuleTracker != null) {
index 0481d9d719eae8bcc9d79e61c7f40ef0e71c695a..6ec0f1995cebd9d11f18ea624d278681aab929cc 100644 (file)
@@ -14,6 +14,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataTreeIdentifier;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigMappingService;
 import org.opendaylight.protocol.bgp.rib.impl.ApplicationPeer;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer.WriteConfiguration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbor.group.Config;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
@@ -33,7 +34,7 @@ public class AppPeer implements PeerBean {
     private Neighbor currentConfiguration;
 
     @Override
-    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService) {
+    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService, final WriteConfiguration configurationWriter) {
         this.currentConfiguration = Preconditions.checkNotNull(neighbor);
         final ApplicationRibId appRibId = createAppRibId(neighbor);
         this.applicationPeer = new ApplicationPeer(appRibId, neighbor.getNeighborAddress().getIpv4Address(), rib);
@@ -46,7 +47,7 @@ public class AppPeer implements PeerBean {
     @Override
     public void restart(final RIB rib, final BGPOpenConfigMappingService mappingService) {
         Preconditions.checkState(this.currentConfiguration != null);
-        start(rib, this.currentConfiguration, mappingService);
+        start(rib, this.currentConfiguration, mappingService, null);
     }
 
     @Override
@@ -57,6 +58,11 @@ public class AppPeer implements PeerBean {
         }
     }
 
+    @Override
+    public Boolean containsEqualConfiguration(final Neighbor neighbor) {
+        return this.currentConfiguration.equals(neighbor);
+    }
+
     private static ApplicationRibId createAppRibId(final Neighbor neighbor) {
         final Config config = neighbor.getConfig();
         if (config != null && !Strings.isNullOrEmpty(config.getDescription())) {
index 0804d72c58d5ce3cb842f170d400d7735c5ae839..e014f3f7d64291ff2d8bf60dbc965e3225d618cf 100644 (file)
@@ -80,8 +80,7 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
         this.container = Preconditions.checkNotNull(container);
         this.bundleContext = Preconditions.checkNotNull(bundleContext);
         this.mappingService = Preconditions.checkNotNull(mappingService);
-        this.networkInstanceIId = InstanceIdentifier
-            .create(NetworkInstances.class)
+        this.networkInstanceIId = InstanceIdentifier.create(NetworkInstances.class)
             .child(NetworkInstance.class, new NetworkInstanceKey(networkInstanceName));
         Futures.addCallback(initializeNetworkInstance(dataBroker, this.networkInstanceIId), new FutureCallback<Void>() {
             @Override
@@ -95,10 +94,7 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
             }
         });
         this.registration = dataBroker.registerDataTreeChangeListener(new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION,
-            this.networkInstanceIId.child(Protocols.class)
-                .child(Protocol.class)
-                .augmentation(Protocol1.class)
-                .child(Bgp.class)), this);
+            this.networkInstanceIId.child(Protocols.class).child(Protocol.class).augmentation(Protocol1.class).child(Bgp.class)), this);
         LOG.info("BGP Deployer {} started.", networkInstanceName);
     }
 
@@ -153,26 +149,27 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
             break;
         case SUBTREE_MODIFIED:
         case WRITE:
-            onGlobalModified(rootIdentifier, dataObjectModification.getDataAfter());
+            onGlobalModified(rootIdentifier, dataObjectModification.getDataAfter(), null);
             break;
         default:
             break;
         }
     }
 
-    private void onGlobalModified(final InstanceIdentifier<Bgp> rootIdentifier, final Global global) {
-        LOG.debug("Modifing RIB instance with configuration: {}", global);
+    @Override
+    public synchronized void onGlobalModified(final InstanceIdentifier<Bgp> rootIdentifier, final Global global,
+        final WriteConfiguration configurationWriter) {
+        LOG.debug("Modifying RIB instance with configuration: {}", global);
         //restart existing rib instance with a new configuration
         final RibImpl ribImpl = this.ribs.get(rootIdentifier);
         if(ribImpl == null ) {
-            //if not exists, create a new instance
-            onGlobalCreated(rootIdentifier, global, null);
+            onGlobalCreated(rootIdentifier, global, configurationWriter);
         } else if (!ribImpl.isGlobalEqual(global)) {
             final List<PeerBean> closedPeers = closeAllBindedPeers(rootIdentifier);
             ribImpl.close();
-            initiateRibInstance(rootIdentifier, global, ribImpl, null);
+            initiateRibInstance(rootIdentifier, global, ribImpl, configurationWriter);
             closedPeers.forEach(peer -> peer.restart(ribImpl, this.mappingService));
-        }
+       }
         LOG.debug("RIB instance modified {}", ribImpl);
     }
 
@@ -188,9 +185,8 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
         return filtered;
     }
 
-    @Override
-    public synchronized void onGlobalCreated(final InstanceIdentifier<Bgp> rootIdentifier, final Global global, final WriteConfiguration
-        configurationWriter) {
+    private synchronized void onGlobalCreated(final InstanceIdentifier<Bgp> rootIdentifier, final Global global,
+        final WriteConfiguration configurationWriter) {
         LOG.debug("Creating RIB instance with configuration: {}", global);
         final RibImpl ribImpl = (RibImpl) this.container.getComponentInstance(InstanceType.RIB.getBeanName());
         initiateRibInstance(rootIdentifier, global, ribImpl, configurationWriter);
@@ -231,7 +227,7 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
                 break;
             case SUBTREE_MODIFIED:
             case WRITE:
-                onNeighborModified(rootIdentifier, (Neighbor) neighborModification.getDataAfter());
+                onNeighborModified(rootIdentifier, (Neighbor) neighborModification.getDataAfter(), null);
                 break;
             default:
                 break;
@@ -239,23 +235,24 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
         }
     }
 
-    private void onNeighborModified(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor) {
-        LOG.debug("Modifing Peer instance with configuration: {}", neighbor);
+    @Override
+    public synchronized void onNeighborModified(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor,
+        final WriteConfiguration configurationWriter) {
+        LOG.debug("Modifying Peer instance with configuration: {}", neighbor);
         //restart peer instance with a new configuration
         final PeerBean bgpPeer = this.peers.get(getNeighborInstanceIdentifier(rootIdentifier, neighbor.getKey()));
-        if (bgpPeer != null) {
+        if (bgpPeer == null) {
+            onNeighborCreated(rootIdentifier, neighbor, configurationWriter);
+        } else if(!bgpPeer.containsEqualConfiguration(neighbor)){
             bgpPeer.close();
             final InstanceIdentifier<Neighbor> neighborInstanceIdentifier = getNeighborInstanceIdentifier(rootIdentifier, neighbor.getKey());
-            initiatePeerInstance(rootIdentifier, neighborInstanceIdentifier, neighbor, bgpPeer);
-        } else {
-            //create new instance, if none is present
-            onNeighborCreated(rootIdentifier, neighbor);
+            initiatePeerInstance(rootIdentifier, neighborInstanceIdentifier, neighbor, bgpPeer, configurationWriter);
         }
         LOG.debug("Peer instance modified {}", bgpPeer);
     }
 
-    private void onNeighborCreated(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor) {
-        //create, start and register peer instance
+    private synchronized void onNeighborCreated(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor,
+        final WriteConfiguration configurationWriter) {
         LOG.debug("Creating Peer instance with configuration: {}", neighbor);
         final PeerBean bgpPeer;
         if (this.mappingService.isApplicationPeer(neighbor)) {
@@ -264,13 +261,13 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
             bgpPeer = (PeerBean) this.container.getComponentInstance(InstanceType.PEER.getBeanName());
         }
         final InstanceIdentifier<Neighbor> neighborInstanceIdentifier = getNeighborInstanceIdentifier(rootIdentifier, neighbor.getKey());
-        initiatePeerInstance(rootIdentifier, neighborInstanceIdentifier, neighbor, bgpPeer);
+        initiatePeerInstance(rootIdentifier, neighborInstanceIdentifier, neighbor, bgpPeer, configurationWriter);
         this.peers.put(neighborInstanceIdentifier, bgpPeer);
         LOG.debug("Peer instance created {}", bgpPeer);
     }
 
-    private void onNeighborRemoved(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor) {
-        //destroy peer instance
+    @Override
+    public synchronized void onNeighborRemoved(final InstanceIdentifier<Bgp> rootIdentifier, final Neighbor neighbor) {
         LOG.debug("Removing Peer instance: {}", rootIdentifier);
         final PeerBean bgpPeer = this.peers.remove(getNeighborInstanceIdentifier(rootIdentifier, neighbor.getKey()));
         if (bgpPeer != null) {
@@ -287,11 +284,11 @@ public final class BgpDeployerImpl implements BgpDeployer, ClusteredDataTreeChan
     }
 
     private void initiatePeerInstance(final InstanceIdentifier<Bgp> rootIdentifier, final InstanceIdentifier<Neighbor> neighborIdentifier, final Neighbor neighbor,
-            final PeerBean bgpPeer) {
+        final PeerBean bgpPeer, final WriteConfiguration configurationWriter) {
         final String peerInstanceName = getNeighborInstanceName(neighborIdentifier);
         final RibImpl rib = this.ribs.get(rootIdentifier);
         if (rib != null) {
-            bgpPeer.start(rib, neighbor, this.mappingService);
+            bgpPeer.start(rib, neighbor, this.mappingService, configurationWriter);
             if (bgpPeer instanceof BgpPeer) {
                 registerPeerInstance((BgpPeer) bgpPeer, peerInstanceName);
             }
index 7159c704b41c9f5ad4996c4d126618d5dfb2f4a7..38b41787f61fbf7801a9313737a5050e3e8e7cdf 100644 (file)
@@ -14,19 +14,27 @@ import static org.opendaylight.protocol.bgp.rib.impl.config.OpenConfigMappingUti
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.util.concurrent.Future;
+import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.List;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BGPPeerRuntimeMXBean;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpPeerState;
 import org.opendaylight.controller.config.yang.bgp.rib.impl.BgpSessionState;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
+import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigMappingService;
 import org.opendaylight.protocol.bgp.parser.BgpExtendedMessageUtil;
 import org.opendaylight.protocol.bgp.parser.spi.MultiprotocolCapabilitiesUtil;
 import org.opendaylight.protocol.bgp.rib.impl.BGPPeer;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionPreferences;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer.WriteConfiguration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.protocol.concepts.KeyMapping;
 import org.opendaylight.protocol.util.Ipv4Util;
@@ -55,12 +63,9 @@ public class BgpPeer implements PeerBean, BGPPeerRuntimeMXBean {
 
     private final RpcProviderRegistry rpcRegistry;
     private final BGPPeerRegistry peerRegistry;
-    private BGPPeer bgpPeer;
-
-    private Future<Void> connection;
-
     private ServiceRegistration<?> serviceRegistration;
     private Neighbor currentConfiguration;
+    private BgpPeerSingletonService bgpPeerSingletonService;
 
     public BgpPeer(final RpcProviderRegistry rpcRegistry, final BGPPeerRegistry peerRegistry) {
         this.rpcRegistry = rpcRegistry;
@@ -68,49 +73,39 @@ public class BgpPeer implements PeerBean, BGPPeerRuntimeMXBean {
     }
 
     @Override
-    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService) {
-        Preconditions.checkState(this.bgpPeer == null, "Previous peer instance {} was not closed.");
-        this.currentConfiguration = Preconditions.checkNotNull(neighbor);
-        final IpAddress neighborAddress = neighbor.getNeighborAddress();
-        this.bgpPeer = new BGPPeer(Ipv4Util.toStringIP(neighborAddress), rib,
-                mappingService.toPeerRole(neighbor), this.rpcRegistry);
-        final List<BgpParameters> bgpParameters = getBgpParameters(neighbor, rib, mappingService);
-        final KeyMapping key = OpenConfigMappingUtil.getNeighborKey(neighbor);
-        final BGPSessionPreferences prefs = new BGPSessionPreferences(rib.getLocalAs(),
-                getHoldTimer(neighbor), rib.getBgpIdentifier(), getPeerAs(neighbor, rib), bgpParameters, getPassword(key));
-        this.peerRegistry.addPeer(neighborAddress, this.bgpPeer, prefs);
-        if (OpenConfigMappingUtil.isActive(neighbor)) {
-            this.connection = rib.getDispatcher().createReconnectingClient(
-                    Ipv4Util.toInetSocketAddress(neighborAddress, OpenConfigMappingUtil.getPort(neighbor)), this.peerRegistry,
-                    OpenConfigMappingUtil.getRetryTimer(neighbor), Optional.fromNullable(key));
-        }
-
+    public void start(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService,
+        final WriteConfiguration configurationWriter) {
+        Preconditions.checkState(this.bgpPeerSingletonService == null, "Previous peer instance {} was not closed.");
+        this.bgpPeerSingletonService = new BgpPeerSingletonService(rib, neighbor, mappingService, configurationWriter);
+        this.currentConfiguration = neighbor;
     }
 
     @Override
     public void restart(final RIB rib, final BGPOpenConfigMappingService mappingService) {
         Preconditions.checkState(this.currentConfiguration != null);
-        start(rib, this.currentConfiguration, mappingService);
+        start(rib, this.currentConfiguration, mappingService, null);
     }
 
     @Override
     public void close() {
-        if (this.bgpPeer != null) {
-            if (this.connection != null) {
-                this.connection.cancel(true);
-                this.connection = null;
-            }
-            this.bgpPeer.close();
-            this.bgpPeer = null;
-            this.peerRegistry.removePeer(this.currentConfiguration.getNeighborAddress());
-            this.currentConfiguration = null;
-            if (this.serviceRegistration != null) {
-                this.serviceRegistration.unregister();
-                this.serviceRegistration = null;
-            }
+        try {
+            this.bgpPeerSingletonService.close();
+            this.bgpPeerSingletonService = null;
+        } catch (final Exception e) {
+            LOG.warn("Failed to close peer instance", e);
+        }
+        this.currentConfiguration = null;
+        if (this.serviceRegistration != null) {
+            this.serviceRegistration.unregister();
+            this.serviceRegistration = null;
         }
     }
 
+    @Override
+    public Boolean containsEqualConfiguration(final Neighbor neighbor) {
+        return this.currentConfiguration.equals(neighbor);
+    }
+
     private static List<BgpParameters> getBgpParameters(final Neighbor neighbor, final RIB rib,
             final BGPOpenConfigMappingService mappingService) {
         final List<BgpParameters> tlvs = new ArrayList<>();
@@ -152,28 +147,103 @@ public class BgpPeer implements PeerBean, BGPPeerRuntimeMXBean {
 
     @Override
     public BgpPeerState getBgpPeerState() {
-        return this.bgpPeer.getBgpPeerState();
+        return this.bgpPeerSingletonService.getPeer().getBgpPeerState();
     }
 
     @Override
     public BgpSessionState getBgpSessionState() {
-        return this.bgpPeer.getBgpSessionState();
+        return this.bgpPeerSingletonService.getPeer().getBgpSessionState();
     }
 
     @Override
-    public void resetStats() {
-        this.bgpPeer.resetStats();
-
+    public void resetSession() {
+        this.bgpPeerSingletonService.getPeer().resetSession();
     }
 
     @Override
-    public void resetSession() {
-        this.bgpPeer.resetSession();
-
+    public void resetStats() {
+        this.bgpPeerSingletonService.getPeer().resetStats();
     }
 
-    public void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
+    void setServiceRegistration(final ServiceRegistration<?> serviceRegistration) {
         this.serviceRegistration = serviceRegistration;
     }
 
+    private final class BgpPeerSingletonService implements ClusterSingletonService, AutoCloseable {
+        private final ServiceGroupIdentifier serviceGroupIdentifier;
+        private final boolean activeConnection;
+        private final BGPDispatcher dispatcher;
+        private final InetSocketAddress inetAddress;
+        private final int retryTimer;
+        private final Optional<KeyMapping> key;
+        private final WriteConfiguration configurationWriter;
+        private ClusterSingletonServiceRegistration registration;
+        private final BGPPeer bgpPeer;
+        private final IpAddress neighborAddress;
+        private final BGPSessionPreferences prefs;
+        private Future<Void> connection;
+
+        private BgpPeerSingletonService(final RIB rib, final Neighbor neighbor, final BGPOpenConfigMappingService mappingService,
+            final WriteConfiguration configurationWriter) {
+            this.neighborAddress = neighbor.getNeighborAddress();
+            this.bgpPeer = new BGPPeer(Ipv4Util.toStringIP(this.neighborAddress), rib, mappingService.toPeerRole(neighbor), rpcRegistry);
+            final List<BgpParameters> bgpParameters = getBgpParameters(neighbor, rib, mappingService);
+            final KeyMapping key = OpenConfigMappingUtil.getNeighborKey(neighbor);
+            this.prefs = new BGPSessionPreferences(rib.getLocalAs(), getHoldTimer(neighbor), rib.getBgpIdentifier(), getPeerAs(neighbor, rib),
+                bgpParameters, getPassword(key));
+            this.activeConnection = OpenConfigMappingUtil.isActive(neighbor);
+            this.dispatcher = rib.getDispatcher();
+            this.inetAddress = Ipv4Util.toInetSocketAddress(this.neighborAddress, OpenConfigMappingUtil.getPort(neighbor));
+            this.retryTimer = OpenConfigMappingUtil.getRetryTimer(neighbor);
+            this.key = Optional.fromNullable(key);
+            this.serviceGroupIdentifier = rib.getRibIServiceGroupIdentifier();
+            LOG.info("Peer Singleton Service {} registered", this.serviceGroupIdentifier);
+            this.registration = rib.registerClusterSingletonService(this);
+            this.configurationWriter = configurationWriter;
+        }
+
+        @Override
+        public void close() throws Exception {
+            if (this.registration != null) {
+                this.registration.close();
+                this.registration = null;
+            }
+        }
+
+        @Override
+        public void instantiateServiceInstance() {
+            if(this.configurationWriter != null) {
+                this.configurationWriter.apply();
+            }
+            LOG.info("Peer Singleton Service {} instantiated", getIdentifier());
+            this.bgpPeer.instantiateServiceInstance();
+            peerRegistry.addPeer(this.neighborAddress, this.bgpPeer, prefs);
+            if (this.activeConnection) {
+                this.connection = this.dispatcher.createReconnectingClient(this.inetAddress, peerRegistry, this.retryTimer, this.key);
+            }
+        }
+
+        @Override
+        public ListenableFuture<Void> closeServiceInstance() {
+            LOG.info("Close RIB Singleton Service {}", this.getIdentifier());
+            if (this.connection != null) {
+                this.connection.cancel(true);
+                this.connection = null;
+            }
+            this.bgpPeer.close();
+            if(currentConfiguration != null) {
+                peerRegistry.removePeer(currentConfiguration.getNeighborAddress());
+            }
+            return Futures.immediateFuture(null);
+        }
+
+        @Override
+        public ServiceGroupIdentifier getIdentifier() {
+            return this.serviceGroupIdentifier;
+        }
+
+        BGPPeerRuntimeMXBean getPeer() {
+            return this.bgpPeer;
+        }
+    }
 }
index 2ebf98c524c2aa1006d6939c0b08676c8378be4f..a640494490eb626f9a93b3c0e4d53aabf3b77d01 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.protocol.bgp.rib.impl.config;
 
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigMappingService;
+import org.opendaylight.protocol.bgp.rib.impl.spi.BgpDeployer.WriteConfiguration;
 import org.opendaylight.protocol.bgp.rib.impl.spi.RIB;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
 
@@ -18,11 +19,12 @@ import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.n
  */
 public interface PeerBean extends AutoCloseable {
 
-    void start(RIB rib, Neighbor neighbor, BGPOpenConfigMappingService mappingService);
+    void start(RIB rib, Neighbor neighbor, BGPOpenConfigMappingService mappingService, WriteConfiguration configurationWriter);
 
     void restart(RIB rib, BGPOpenConfigMappingService mappingService);
 
     @Override
     void close();
 
+    Boolean containsEqualConfiguration(Neighbor neighbor);
 }
index b14615bda502da7eb9ff25437ff58bcb4cf7f297..be39e0c4bcf7c8c6b7d4d3f997f0e6de3aa8a79f 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.protocol.bgp.rib.impl.spi;
 
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.protocol.bgp.openconfig.spi.BGPOpenConfigMappingService;
+import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.network.instance.rev151018.network.instance.top.network.instances.NetworkInstance;
@@ -46,11 +47,25 @@ public interface BgpDeployer {
      * @param global
      * @param configurationWriter
      */
-    void onGlobalCreated(InstanceIdentifier<Bgp> rootIdentifier, Global global, WriteConfiguration configurationWriter);
+    void onGlobalModified(InstanceIdentifier<Bgp> rootIdentifier, Global global, WriteConfiguration configurationWriter);
 
     /**
      * Destroy rib instance
      * @param rootIdentifier
      */
     void onGlobalRemoved(InstanceIdentifier<Bgp> rootIdentifier);
+
+    /**
+     * Create, start and register peer instance
+     * @param rootIdentifier
+     * @param neighbor
+     */
+    void onNeighborModified(InstanceIdentifier<Bgp> rootIdentifier, Neighbor neighbor, WriteConfiguration configurationWriter);
+
+    /**
+     * Destroy peer instance
+     * @param rootIdentifier
+     * @param neighbor
+     */
+    void onNeighborRemoved(InstanceIdentifier<Bgp> rootIdentifier, Neighbor neighbor);
 }
index ac21e0280666152e23d29972a5aa826039114a40..46837f00be7173ed4e17efa68d269639983dbba6 100755 (executable)
@@ -285,7 +285,8 @@ public abstract class AbstractRIBImplModuleTest extends AbstractConfigTest {
         doReturn(new ProtocolBuilder().setKey(new ProtocolKey(BGP.class, "bgp"))
             .addAugmentation(Protocol1.class, new Protocol1Builder().setBgp(globalBgp).build()).build())
             .when(this.bgpMappingService).fromRib(any(), any(), any(), any(), any(), any());
-        doNothing().when(this.bgpDeployer).onGlobalCreated(any(),any(),any());
+        doNothing().when(this.bgpDeployer).onGlobalModified(any(),any(),any());
+        doNothing().when(this.bgpDeployer).onNeighborModified(any(),any(),any());
         doReturn(NEIGHBOR).when(this.bgpMappingService).fromBgpPeer(any(), any(),
                 any(), any(), any(), any(), any(), any(), any(), any(), any());
         doReturn(NEIGHBOR).when(this.bgpMappingService).fromApplicationPeer(any(), any());
index 78f265a5a1bf13c7f5feef2c00204d7027000af0..2b5f9b997fc794711855f0d7058022a2309b8628 100755 (executable)
@@ -17,7 +17,6 @@ import java.util.Collections;
 import java.util.List;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.ObjectName;
-import org.junit.Assert;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.IdentityAttributeRef;
 import org.opendaylight.controller.config.api.ValidationException;
@@ -41,7 +40,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
     private static final String FACTORY_NAME = BGPPeerModuleFactory.NAME;
 
     private static final IpAddress HOST = new IpAddress(new Ipv4Address("127.0.0.1"));
-    private static final PortNumber portNumber = new PortNumber(1);
+    private static final PortNumber PORT_NUMBER = new PortNumber(1);
 
     @Override
     protected BindingRuntimeContext getBindingRuntimeContext() {
@@ -84,7 +83,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
     @Test
     public void testValidationExceptionHostNotSet() throws Exception {
         try {
-            createBgpPeerInstance(null, portNumber, false);
+            createBgpPeerInstance(null, PORT_NUMBER, false);
             fail();
         } catch (final ValidationException e) {
             assertTrue(e.getMessage().contains("Host value is not set."));
@@ -186,7 +185,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
     }
 
     private CommitStatus createBgpPeerInstance(final boolean md5) throws Exception {
-        return createBgpPeerInstance(HOST, portNumber, md5);
+        return createBgpPeerInstance(HOST, PORT_NUMBER, md5);
     }
 
     private CommitStatus createBgpPeerInstance(final IpAddress host, final PortNumber port, final boolean md5) throws Exception {
@@ -198,7 +197,7 @@ public class BGPPeerModuleTest extends AbstractRIBImplModuleTest {
     private CommitStatus createInternalBgpPeerInstance()
         throws Exception {
         final ConfigTransactionJMXClient transaction = this.configRegistryClient.createTransaction();
-        createBgpPeerInstance(transaction, HOST, portNumber, false, true);
+        createBgpPeerInstance(transaction, HOST, PORT_NUMBER, false, true);
         return transaction.commit();
     }
 }
index 1fa62a242fc664ce7c298ac7143b4c6108e6b1a2..cc3de9c9a03d68a67a116047f3b6f2a48d27ef38 100755 (executable)
@@ -99,7 +99,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
     @Override
     protected java.lang.Iterable<org.opendaylight.yangtools.yang.binding.YangModuleInfo> getModuleInfos() throws Exception {
         return ImmutableList.of(BindingReflections.getModuleInfo(Ipv4Route.class), BindingReflections.getModuleInfo(Ipv6Route.class), BindingReflections.getModuleInfo(LinkstateRoute.class));
-    };
+    }
 
     @Override
     protected DataBrokerTestCustomizer createDataBrokerTestCustomizer() {
@@ -150,7 +150,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
         assertTablesExists(tables, true);
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
         final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib, PeerRole.Ibgp, null);
-
+        peer.instantiateServiceInstance();
         final ListenerRegistration<?> reg = this.mock.registerUpdateListener(peer);
         reg.close();
     }
@@ -165,7 +165,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest {
         rib.onGlobalContextUpdated(this.schemaService.getGlobalContext());
         assertTablesExists(tables, true);
         final BGPPeer peer = new BGPPeer("peer-" + this.mock.toString(), rib, PeerRole.Ibgp, null);
-
+        peer.instantiateServiceInstance();
         final ListenerRegistration<?> reg = this.mock.registerUpdateListener(peer);
         reg.close();
     }
index 9e5f9339b77163b2e2f36d89604119d0cef49ae6..88e10dab90d372c3e4bfd0f0d26f9b28756e778b 100644 (file)
@@ -138,6 +138,7 @@ public class PeerTest extends AbstractRIBTestSetup {
     @Test
     public void testClassicPeer() throws Exception {
         this.classic = new BGPPeer("testPeer", getRib(), PeerRole.Ibgp, null);
+        this.classic.instantiateServiceInstance();
         this.mockSession();
         assertEquals("testPeer", this.classic.getName());
         this.classic.onSessionUp(this.session);
@@ -171,6 +172,7 @@ public class PeerTest extends AbstractRIBTestSetup {
 
         //create new peer so that it gets advertized routes from RIB
         try (final BGPPeer testingPeer = new BGPPeer("testingPeer", getRib(), PeerRole.Ibgp, null)) {
+            testingPeer.instantiateServiceInstance();
             testingPeer.onSessionUp(this.session);
             assertEquals(3, this.routes.size());
             assertEquals(1, testingPeer.getBgpPeerState().getSessionEstablishedCount().getValue().intValue());