From 259daaeb2ad7ebf70308abc0a098ab2ba096b375 Mon Sep 17 00:00:00 2001 From: "Claudio D. Gasparini" Date: Wed, 10 Aug 2016 14:51:42 +0200 Subject: [PATCH] BUG-5685: Register BGP Peer Cluster Singleton Service 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 --- .../yang/bgp/rib/impl/BGPPeerModule.java | 17 +- .../yang/bgp/rib/impl/RIBImplModule.java | 2 +- .../protocol/bgp/rib/impl/BGPPeer.java | 15 +- .../protocol/bgp/rib/impl/RIBImpl.java | 18 +- .../protocol/bgp/rib/impl/config/AppPeer.java | 10 +- .../bgp/rib/impl/config/BgpDeployerImpl.java | 59 ++++--- .../protocol/bgp/rib/impl/config/BgpPeer.java | 158 +++++++++++++----- .../bgp/rib/impl/config/PeerBean.java | 4 +- .../bgp/rib/impl/spi/BgpDeployer.java | 17 +- .../rib/impl/AbstractRIBImplModuleTest.java | 3 +- .../yang/bgp/rib/impl/BGPPeerModuleTest.java | 9 +- .../bgp/rib/impl/ParserToSalTest.java | 6 +- .../protocol/bgp/rib/impl/PeerTest.java | 2 + 13 files changed, 209 insertions(+), 111 deletions(-) diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java index 91ceb1864b..1f33da993c 100755 --- a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModule.java @@ -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 bgpDeployerTracker = - WaitingServiceTracker.create(BgpDeployer.class, this.bundleContext); + final RIB rib = getRibDependency(); + final WaitingServiceTracker 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 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 protocolIId = bgpDeployer.getInstanceIdentifier().child(Protocols.class) + .child(Protocol.class, new ProtocolKey(BGP.class, rib.getInstanceIdentifier().getKey().getId().getValue())); + final InstanceIdentifier bgpIID = protocolIId.augmentation(Protocol1.class).child(Bgp.class); + final KeyedInstanceIdentifier 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 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(); diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java index d6f6cfa8b6..1f8d2cfc63 100755 --- a/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/controller/config/yang/bgp/rib/impl/RIBImplModule.java @@ -85,7 +85,7 @@ public final class RIBImplModule extends org.opendaylight.controller.config.yang final KeyedInstanceIdentifier protocolIId = bgpDeployer.getInstanceIdentifier().child(Protocols.class) .child(Protocol.class, protocol.getKey()); final InstanceIdentifier 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 ribTracker = WaitingServiceTracker.create(RIB.class, diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java index 731b7a5a51..ad269b6dea 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/BGPPeer.java @@ -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(); } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java index 9d708d0ec7..cb8def72e9 100755 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/RIBImpl.java @@ -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 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) { diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java index 0481d9d719..6ec0f1995c 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/AppPeer.java @@ -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())) { diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerImpl.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerImpl.java index 0804d72c58..e014f3f7d6 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerImpl.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpDeployerImpl.java @@ -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() { @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 rootIdentifier, final Global global) { - LOG.debug("Modifing RIB instance with configuration: {}", global); + @Override + public synchronized void onGlobalModified(final InstanceIdentifier 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 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 rootIdentifier, final Global global, final WriteConfiguration - configurationWriter) { + private synchronized void onGlobalCreated(final InstanceIdentifier 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 rootIdentifier, final Neighbor neighbor) { - LOG.debug("Modifing Peer instance with configuration: {}", neighbor); + @Override + public synchronized void onNeighborModified(final InstanceIdentifier 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 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 rootIdentifier, final Neighbor neighbor) { - //create, start and register peer instance + private synchronized void onNeighborCreated(final InstanceIdentifier 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 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 rootIdentifier, final Neighbor neighbor) { - //destroy peer instance + @Override + public synchronized void onNeighborRemoved(final InstanceIdentifier 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 rootIdentifier, final InstanceIdentifier 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); } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java index 7159c704b4..38b41787f6 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/BgpPeer.java @@ -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 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 = 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 getBgpParameters(final Neighbor neighbor, final RIB rib, final BGPOpenConfigMappingService mappingService) { final List 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 key; + private final WriteConfiguration configurationWriter; + private ClusterSingletonServiceRegistration registration; + private final BGPPeer bgpPeer; + private final IpAddress neighborAddress; + private final BGPSessionPreferences prefs; + private Future 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 = 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 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; + } + } } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java index 2ebf98c524..a640494490 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/config/PeerBean.java @@ -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); } diff --git a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BgpDeployer.java b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BgpDeployer.java index b14615bda5..be39e0c4bc 100644 --- a/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BgpDeployer.java +++ b/bgp/rib-impl/src/main/java/org/opendaylight/protocol/bgp/rib/impl/spi/BgpDeployer.java @@ -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 rootIdentifier, Global global, WriteConfiguration configurationWriter); + void onGlobalModified(InstanceIdentifier rootIdentifier, Global global, WriteConfiguration configurationWriter); /** * Destroy rib instance * @param rootIdentifier */ void onGlobalRemoved(InstanceIdentifier rootIdentifier); + + /** + * Create, start and register peer instance + * @param rootIdentifier + * @param neighbor + */ + void onNeighborModified(InstanceIdentifier rootIdentifier, Neighbor neighbor, WriteConfiguration configurationWriter); + + /** + * Destroy peer instance + * @param rootIdentifier + * @param neighbor + */ + void onNeighborRemoved(InstanceIdentifier rootIdentifier, Neighbor neighbor); } diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java index ac21e02806..46837f00be 100755 --- a/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/AbstractRIBImplModuleTest.java @@ -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()); diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java index 78f265a5a1..2b5f9b997f 100755 --- a/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/controller/config/yang/bgp/rib/impl/BGPPeerModuleTest.java @@ -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(); } } diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java index 1fa62a242f..cc3de9c9a0 100755 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/ParserToSalTest.java @@ -99,7 +99,7 @@ public class ParserToSalTest extends AbstractDataBrokerTest { @Override protected java.lang.Iterable 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(); } diff --git a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java index 9e5f9339b7..88e10dab90 100644 --- a/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java +++ b/bgp/rib-impl/src/test/java/org/opendaylight/protocol/bgp/rib/impl/PeerTest.java @@ -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()); -- 2.36.6