BUG-6978: Integrate BMP collector with Cluster Singleton Service 12/57612/6
authorClaudio D. Gasparini <claudio.gasparini@pantheon.tech>
Fri, 19 May 2017 10:51:57 +0000 (12:51 +0200)
committerRobert Varga <nite@hq.sk>
Tue, 18 Jul 2017 20:43:35 +0000 (20:43 +0000)
Implement bmp HA by introducing CSS to BmpMonitoringStation

Change-Id: I657c367c33fc6b1946c3db19a71725a78917925a
Signed-off-by: Claudio D. Gasparini <claudio.gasparini@pantheon.tech>
bgp/bmp-impl/src/main/java/org/opendaylight/protocol/bmp/impl/app/BmpMonitoringStationImpl.java
bgp/bmp-impl/src/main/java/org/opendaylight/protocol/bmp/impl/config/BmpDeployerDependencies.java
bgp/bmp-impl/src/main/java/org/opendaylight/protocol/bmp/impl/config/BmpDeployerImpl.java
bgp/bmp-impl/src/main/java/org/opendaylight/protocol/bmp/impl/spi/BmpMonitoringStation.java
bgp/bmp-impl/src/main/resources/org/opendaylight/blueprint/bgp-bmp.xml
bgp/bmp-impl/src/test/java/org/opendaylight/protocol/bmp/impl/app/BmpMonitorImplTest.java

index 370573140df596a5c1ff8c385575e5b0f2ffa3ae..1027211099e78fd11cb860941b9203b4158e9a9f 100644 (file)
@@ -13,18 +13,21 @@ import static org.opendaylight.protocol.bmp.impl.app.KeyConstructorUtil.construc
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.util.List;
+import javax.annotation.Nonnull;
+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.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
-import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
 import org.opendaylight.protocol.bmp.api.BmpDispatcher;
 import org.opendaylight.protocol.bmp.impl.config.BmpDeployerDependencies;
 import org.opendaylight.protocol.bmp.impl.spi.BmpMonitoringStation;
@@ -38,41 +41,89 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bmp.moni
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.rfc2385.cfg.rev160324.Rfc2385Key;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public final class BmpMonitoringStationImpl implements BmpMonitoringStation {
+public final class BmpMonitoringStationImpl implements BmpMonitoringStation, ClusterSingletonService {
 
     private static final Logger LOG = LoggerFactory.getLogger(BmpMonitoringStationImpl.class);
 
     private static final QName MONITOR_ID_QNAME = QName.create(Monitor.QNAME, "monitor-id").intern();
+    private static final ServiceGroupIdentifier SERVICE_GROUP_IDENTIFIER =
+        ServiceGroupIdentifier.create("bmp-monitors-service-group");
 
     private final DOMDataBroker domDataBroker;
-    private final YangInstanceIdentifier yangMonitorId;
-    private final RouterSessionManager sessionManager;
-    private final Channel channel;
+    private final InetSocketAddress address;
     private final MonitorId monitorId;
     private final List<MonitoredRouter> monitoredRouters;
-
-    private BmpMonitoringStationImpl(final DOMDataBroker domDataBroker, final YangInstanceIdentifier yangMonitorId,
-            final Channel channel, final RouterSessionManager sessionManager, final MonitorId monitorId,
-            final BmpDispatcher dispatcher, final List<MonitoredRouter> mrs) {
-        this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
-        this.yangMonitorId = Preconditions.checkNotNull(yangMonitorId);
-        this.channel = Preconditions.checkNotNull(channel);
-        this.sessionManager = Preconditions.checkNotNull(sessionManager);
+    private final BmpDispatcher dispatcher;
+    private final RouterSessionManager sessionManager;
+    private final YangInstanceIdentifier yangMonitorId;
+    private Channel channel;
+    private ClusterSingletonServiceRegistration singletonServiceRegistration;
+
+    public BmpMonitoringStationImpl(final BmpDeployerDependencies bmpDeployerDependencies,
+        final BmpDispatcher dispatcher, final MonitorId monitorId, final InetSocketAddress address,
+        final List<MonitoredRouter> mrs) {
+        this.domDataBroker = Preconditions.checkNotNull(bmpDeployerDependencies.getDomDataBroker());
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
         this.monitorId = monitorId;
         this.monitoredRouters = mrs;
+        this.address = Preconditions.checkNotNull(address);
+
+        this.yangMonitorId = YangInstanceIdentifier.builder()
+            .node(BmpMonitor.QNAME).node(Monitor.QNAME)
+            .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build();
+
+        this.sessionManager = new RouterSessionManager(this.yangMonitorId, this.domDataBroker,
+            bmpDeployerDependencies.getExtensions(), bmpDeployerDependencies.getTree());
+
+        LOG.info("BMP Monitor Singleton Service {} registered, Monitor Id {}",
+            getIdentifier().getValue(), this.monitorId.getValue());
+        this.singletonServiceRegistration = bmpDeployerDependencies.getClusterSingletonProvider()
+            .registerClusterSingletonService(this);
+    }
 
-        createEmptyMonitor();
-        LOG.info("BMP Monitoring station {} started", this.monitorId.getValue());
+    @Override
+    public synchronized void instantiateServiceInstance() {
+        LOG.info("BMP Monitor Singleton Service {} instantiated, Monitor Id {}",
+            getIdentifier().getValue(), this.monitorId.getValue());
+
+        final ChannelFuture channelFuture = this.dispatcher.createServer(this.address, this.sessionManager,
+            constructKeys(this.monitoredRouters));
+        try {
+            this.channel = channelFuture.sync().channel();
+            createEmptyMonitor();
+            LOG.info("BMP Monitoring station {} started", this.monitorId.getValue());
+
+            connectMonitoredRouters(this.dispatcher);
+            LOG.info("Connecting to monitored routers completed.");
+        } catch (final InterruptedException e) {
+            LOG.error("Failed to instantiate BMP Monitor Singleton {}", this.monitorId.getValue(), e);
+        }
+
+    }
+
+    @Override
+    public synchronized ListenableFuture<Void> closeServiceInstance() {
+        LOG.info("BMP Monitor Singleton Service {} instance closed, Monitor Id {}",
+            getIdentifier().getValue(), this.monitorId.getValue());
+        this.channel.close().addListener((ChannelFutureListener) future -> {
+            Preconditions.checkArgument(future.isSuccess(), "Channel failed to close: %s", future.cause());
+            BmpMonitoringStationImpl.this.sessionManager.close();
+        });
+
+        final DOMDataWriteTransaction wTx = this.domDataBroker.newWriteOnlyTransaction();
+        wTx.delete(LogicalDatastoreType.OPERATIONAL, this.yangMonitorId);
+        LOG.info("BMP monitoring station {} closed.", this.monitorId.getValue());
+        return wTx.submit();
+    }
 
-        connectMonitoredRouters(dispatcher);
-        LOG.info("Connecting to monitored routers completed.");
+    @Nonnull
+    @Override
+    public ServiceGroupIdentifier getIdentifier() {
+        return SERVICE_GROUP_IDENTIFIER;
     }
 
     private void connectMonitoredRouters(final BmpDispatcher dispatcher) {
@@ -93,48 +144,15 @@ public final class BmpMonitoringStationImpl implements BmpMonitoringStation {
         }
     }
 
-    public static BmpMonitoringStation createBmpMonitorInstance(final BmpDeployerDependencies bmpDeployerDependencies,
-        final BmpDispatcher dispatcher, final MonitorId monitorId, final InetSocketAddress inetAddress,
-        final List<MonitoredRouter> monitoredRouter) throws InterruptedException {
-        return createBmpMonitorInstance(bmpDeployerDependencies.getExtensions(), dispatcher,
-            bmpDeployerDependencies.getDomDataBroker(), bmpDeployerDependencies.getTree(), monitorId, inetAddress,
-            monitoredRouter);
-
-    }
-
-    public static BmpMonitoringStation createBmpMonitorInstance(final RIBExtensionConsumerContext ribExtensions,
-        final BmpDispatcher dispatcher, final DOMDataBroker domDataBroker, final BindingCodecTree tree,
-        final MonitorId monitorId, final InetSocketAddress address, final List<MonitoredRouter> mrs)
-        throws InterruptedException {
-
-        final YangInstanceIdentifier yangMonitorId = YangInstanceIdentifier.builder()
-            .node(BmpMonitor.QNAME).node(Monitor.QNAME)
-            .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, monitorId.getValue()).build();
-
-        final RouterSessionManager sessionManager = new RouterSessionManager(yangMonitorId, domDataBroker,
-            ribExtensions, tree);
-        final ChannelFuture channelFuture = dispatcher.createServer(address, sessionManager, constructKeys(mrs));
-
-        return new BmpMonitoringStationImpl(domDataBroker, yangMonitorId, channelFuture.sync().channel(),
-            sessionManager, monitorId, dispatcher, mrs);
-    }
-
-    private static void ensureParentExists(final DOMDataWriteTransaction wTx, final YangInstanceIdentifier path) {
-        final ContainerNode parentNode = Builders.containerBuilder().withNodeIdentifier(
-                new NodeIdentifier(BmpMonitor.QNAME)).addChild(ImmutableNodes.mapNodeBuilder(Monitor.QNAME).build()).build();
-        wTx.merge(LogicalDatastoreType.OPERATIONAL, path, parentNode);
-    }
-
     private synchronized void createEmptyMonitor() {
         final DOMDataWriteTransaction wTx = this.domDataBroker.newWriteOnlyTransaction();
-        ensureParentExists(wTx, YangInstanceIdentifier.of(BmpMonitor.QNAME));
         wTx.put(LogicalDatastoreType.OPERATIONAL,
-                YangInstanceIdentifier.builder().node(BmpMonitor.QNAME).node(Monitor.QNAME)
-                    .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, this.monitorId.getValue()).build(),
-                ImmutableNodes.mapEntryBuilder(Monitor.QNAME, MONITOR_ID_QNAME, this.monitorId.getValue())
-                    .addChild(ImmutableNodes.leafNode(MONITOR_ID_QNAME, this.monitorId.getValue()))
-                    .addChild(ImmutableNodes.mapNodeBuilder(Router.QNAME).build())
-                    .build());
+            YangInstanceIdentifier.builder().node(BmpMonitor.QNAME).node(Monitor.QNAME)
+                .nodeWithKey(Monitor.QNAME, MONITOR_ID_QNAME, this.monitorId.getValue()).build(),
+            ImmutableNodes.mapEntryBuilder(Monitor.QNAME, MONITOR_ID_QNAME, this.monitorId.getValue())
+                .addChild(ImmutableNodes.leafNode(MONITOR_ID_QNAME, this.monitorId.getValue()))
+                .addChild(ImmutableNodes.mapNodeBuilder(Router.QNAME).build())
+                .build());
         try {
             wTx.submit().checkedGet();
         } catch (final TransactionCommitFailedException e) {
@@ -144,11 +162,9 @@ public final class BmpMonitoringStationImpl implements BmpMonitoringStation {
 
     @Override
     public synchronized void close() throws Exception {
-        this.channel.close().addListener((ChannelFutureListener) channelFuture -> BmpMonitoringStationImpl.this.sessionManager.close()).await();
-
-        final DOMDataWriteTransaction wTx = this.domDataBroker.newWriteOnlyTransaction();
-        wTx.delete(LogicalDatastoreType.OPERATIONAL, this.yangMonitorId);
-        wTx.submit().checkedGet();
-        LOG.info("BMP monitoring station {} closed.", this.monitorId.getValue());
+        if (this.singletonServiceRegistration != null) {
+            this.singletonServiceRegistration.close();
+            this.singletonServiceRegistration = null;
+        }
     }
 }
index a34f69f7ddeabe0510517f04b832c26f26eb35a6..d90e3dc4aee9002430ced65f8963ff9544286713 100644 (file)
@@ -12,6 +12,7 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
 import org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
@@ -20,14 +21,16 @@ public class BmpDeployerDependencies {
     private final RIBExtensionConsumerContext extensions;
     private final BindingCodecTree tree;
     private final DOMDataBroker domDataBroker;
+    private final ClusterSingletonServiceProvider singletonProvider;
 
     public BmpDeployerDependencies(final DataBroker dataBroker, final DOMDataBroker domDataBroker,
     final RIBExtensionConsumerContext extensions, final BindingCodecTreeFactory codecTreeFactory,
-    final SchemaContext schemaContext) {
+    final SchemaContext schemaContext, final ClusterSingletonServiceProvider singletonProvider) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.domDataBroker = Preconditions.checkNotNull(domDataBroker);
         this.extensions = Preconditions.checkNotNull(extensions);
         this.tree = Preconditions.checkNotNull(codecTreeFactory).create(schemaContext);
+        this.singletonProvider = Preconditions.checkNotNull(singletonProvider);
     }
 
     public DataBroker getDataBroker() {
@@ -45,4 +48,8 @@ public class BmpDeployerDependencies {
     public DOMDataBroker getDomDataBroker() {
         return this.domDataBroker;
     }
+
+    public ClusterSingletonServiceProvider getClusterSingletonProvider() {
+        return this.singletonProvider;
+    }
 }
index 7cec03e76f5f14a4f7e7dce047938b87ad6c3997..3b5b959af7c99c3f4e969ba72671e0789e030dea 100644 (file)
@@ -13,7 +13,6 @@ import java.net.InetSocketAddress;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.ExecutionException;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
@@ -59,7 +58,7 @@ public class BmpDeployerImpl implements BmpDeployer, ClusteredDataTreeChangeList
         new NodeIdentifier(BmpMonitor.QNAME)).addChild(ImmutableNodes.mapNodeBuilder(Monitor.QNAME).build()).build();
     private final BmpDispatcher dispatcher;
     @GuardedBy("this")
-    private final Map<MonitorId, BmpMonitoringStation> bmpMonitorServices = new HashMap<>();
+    private final Map<MonitorId, BmpMonitoringStationImpl> bmpMonitorServices = new HashMap<>();
     private final BmpDeployerDependencies bmpDeployerDependencies;
     @GuardedBy("this")
     private ListenerRegistration<BmpDeployerImpl> registration;
@@ -75,7 +74,6 @@ public class BmpDeployerImpl implements BmpDeployer, ClusteredDataTreeChangeList
         wTx.submit();
         this.registration = this.bmpDeployerDependencies.getDataBroker().registerDataTreeChangeListener(
             new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, ODL_BMP_MONITORS_IID), this);
-
     }
 
     @Override
@@ -107,17 +105,18 @@ public class BmpDeployerImpl implements BmpDeployer, ClusteredDataTreeChangeList
 
     private void updateBmpMonitor(final BmpMonitorConfig bmpConfig) {
         final MonitorId monitorId = bmpConfig.getMonitorId();
-        final BmpMonitoringStation oldService = this.bmpMonitorServices.remove(monitorId);
+        final BmpMonitoringStationImpl oldService = this.bmpMonitorServices.remove(monitorId);
         try {
             if (oldService != null) {
+                oldService.closeServiceInstance().get();
                 oldService.close();
             }
 
             final Server server = bmpConfig.getServer();
             final InetSocketAddress inetAddress =
                 Ipv4Util.toInetSocketAddress(server.getBindingAddress(), server.getBindingPort());
-            final BmpMonitoringStation monitor = BmpMonitoringStationImpl.createBmpMonitorInstance(
-                this.bmpDeployerDependencies, this.dispatcher, monitorId, inetAddress, bmpConfig.getMonitoredRouter());
+            final BmpMonitoringStationImpl monitor = new BmpMonitoringStationImpl(this.bmpDeployerDependencies,
+                this.dispatcher, monitorId, inetAddress, bmpConfig.getMonitoredRouter());
             this.bmpMonitorServices.put(monitorId, monitor);
         } catch (final Exception e) {
             LOG.error("Failed to create Bmp Monitor {}.", monitorId, e);
index e320e9ce2d6cef21286e08a0386aa3bb42b3b42c..4eafdcf38eef7d94e2083b1cdbb90049cec6c3fc 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.protocol.bmp.impl.spi;
 
-
 public interface BmpMonitoringStation extends AutoCloseable {
 
 }
index 61c37fa13f9908b2afd50e0621ea2f5c975c2b6e..cd276b64e1612b60bd16a81a36969ea3a248c87b 100644 (file)
   </service>
 
   <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker" odl:type="default"/>
-  <reference id="domPingPongDataBroker" interface="org.opendaylight.controller.md.sal.dom.api.DOMDataBroker"
-             odl:type="pingpong"/>
+  <reference id="domPingPongDataBroker" interface="org.opendaylight.controller.md.sal.dom.api.DOMDataBroker" odl:type="pingpong"/>
   <reference id="globalBgpExtensions" interface="org.opendaylight.protocol.bgp.rib.spi.RIBExtensionConsumerContext"/>
   <reference id="codecTreeFactory" interface="org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeFactory"/>
   <odl:static-reference id="domSchemaService" interface="org.opendaylight.mdsal.dom.api.DOMSchemaService"/>
+  <reference id="clusterSingletonServiceProvider" interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
 
   <bean id="bmpDeployerDependecies" class="org.opendaylight.protocol.bmp.impl.config.BmpDeployerDependencies">
     <argument ref="dataBroker"/>
@@ -42,6 +42,7 @@
     <argument>
       <bean factory-ref="domSchemaService" factory-method="getGlobalContext"/>
     </argument>
+    <argument ref="clusterSingletonServiceProvider"/>
   </bean>
 
   <bean id="bmpDeployer" class="org.opendaylight.protocol.bmp.impl.config.BmpDeployerImpl"
index 7331459532dcf4b3b1117edc357a669e569a5e27..7168519152c7f085e43d69b0346b54dc4f18d4d0 100644 (file)
@@ -14,6 +14,8 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
 import static org.opendaylight.protocol.util.CheckUtil.readDataOperational;
 import static org.opendaylight.protocol.util.CheckUtil.waitFutureSuccess;
 
@@ -36,16 +38,18 @@ import javassist.ClassPool;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
 import org.opendaylight.controller.md.sal.binding.test.AbstractConcurrentDataBrokerTest;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTree;
 import org.opendaylight.mdsal.binding.generator.impl.GeneratedClassLoadingStrategy;
 import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
-import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonService;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
 import org.opendaylight.protocol.bgp.inet.RIBActivator;
 import org.opendaylight.protocol.bgp.parser.impl.BGPActivator;
 import org.opendaylight.protocol.bgp.parser.spi.BGPExtensionProviderContext;
@@ -55,13 +59,13 @@ import org.opendaylight.protocol.bgp.rib.spi.SimpleRIBExtensionProviderContext;
 import org.opendaylight.protocol.bmp.api.BmpDispatcher;
 import org.opendaylight.protocol.bmp.impl.BmpDispatcherImpl;
 import org.opendaylight.protocol.bmp.impl.BmpHandlerFactory;
+import org.opendaylight.protocol.bmp.impl.config.BmpDeployerDependencies;
 import org.opendaylight.protocol.bmp.impl.session.DefaultBmpSessionFactory;
 import org.opendaylight.protocol.bmp.impl.spi.BmpMonitoringStation;
 import org.opendaylight.protocol.bmp.parser.BmpActivator;
 import org.opendaylight.protocol.bmp.parser.message.TestUtil;
 import org.opendaylight.protocol.bmp.spi.registry.BmpMessageRegistry;
 import org.opendaylight.protocol.bmp.spi.registry.SimpleBmpExtensionProviderContext;
-import org.opendaylight.protocol.concepts.KeyMapping;
 import org.opendaylight.protocol.util.CheckUtil;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
@@ -130,15 +134,41 @@ public class BmpMonitorImplTest extends AbstractConcurrentDataBrokerTest {
     private BmpDispatcher dispatcher;
     private BmpMonitoringStation bmpApp;
     private BmpMessageRegistry msgRegistry;
-    private BindingCodecTree tree;
     private RIBExtensionProviderContext ribExtension;
-
-
+    private ClusterSingletonService singletonService;
+    private ClusterSingletonService singletonService2;
+    @Mock
+    private ClusterSingletonServiceRegistration singletonServiceRegistration;
+    @Mock
+    private ClusterSingletonServiceRegistration singletonServiceRegistration2;
+    @Mock
+    private ClusterSingletonServiceProvider clusterSSProv;
+    @Mock
+    private ClusterSingletonServiceProvider clusterSSProv2;
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+
+        doAnswer(invocationOnMock -> {
+            BmpMonitorImplTest.this.singletonService = (ClusterSingletonService) invocationOnMock.getArguments()[0];
+            this.singletonService.instantiateServiceInstance();
+            return BmpMonitorImplTest.this.singletonServiceRegistration;
+        }).when(this.clusterSSProv).registerClusterSingletonService(any(ClusterSingletonService.class));
+
+        doAnswer(invocationOnMock -> BmpMonitorImplTest.this.singletonService.closeServiceInstance())
+            .when(this.singletonServiceRegistration).close();
+
+        doAnswer(invocationOnMock -> {
+            this.singletonService2 = (ClusterSingletonService) invocationOnMock.getArguments()[0];
+            this.singletonService2.instantiateServiceInstance();
+            return BmpMonitorImplTest.this.singletonServiceRegistration2;
+        }).when(this.clusterSSProv2).registerClusterSingletonService(any(ClusterSingletonService.class));
+
+        doAnswer(invocationOnMock -> BmpMonitorImplTest.this.singletonService2.closeServiceInstance())
+            .when(this.singletonServiceRegistration2).close();
+
         this.mappingService = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(),
-                new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()))));
+            new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()))));
         final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
         moduleInfoBackedContext.registerModuleInfo(BindingReflections.getModuleInfo(InitiationMessage.class));
         moduleInfoBackedContext.registerModuleInfo(BindingReflections.getModuleInfo(CParameters1.class));
@@ -150,7 +180,7 @@ public class BmpMonitorImplTest extends AbstractConcurrentDataBrokerTest {
         moduleInfoBackedContext.registerModuleInfo(BindingReflections.getModuleInfo(ReceivedOpen.class));
         this.mappingService.onGlobalContextUpdated(moduleInfoBackedContext.tryToCreateSchemaContext().get());
         this.ribActivator = new RIBActivator();
-         this.ribExtension = new SimpleRIBExtensionProviderContext();
+        this.ribExtension = new SimpleRIBExtensionProviderContext();
         this.ribActivator.startRIBExtensionProvider(this.ribExtension);
 
         this.bgpActivator = new BGPActivator();
@@ -164,10 +194,6 @@ public class BmpMonitorImplTest extends AbstractConcurrentDataBrokerTest {
         this.dispatcher = new BmpDispatcherImpl(new NioEventLoopGroup(), new NioEventLoopGroup(),
             ctx.getBmpMessageRegistry(), new DefaultBmpSessionFactory());
 
-        final BindingRuntimeContext runtimeContext = BindingRuntimeContext.create(this.ribExtension
-            .getClassLoadingStrategy(), this.getSchemaContext());
-        this.tree = this.mappingService.getCodecFactory().create(runtimeContext);
-
         final InetSocketAddress inetAddress = new InetSocketAddress(InetAddresses.forString(MONITOR_LOCAL_ADDRESS),
             MONITOR_LOCAL_PORT);
 
@@ -177,9 +203,9 @@ public class BmpMonitorImplTest extends AbstractConcurrentDataBrokerTest {
         wTx.merge(LogicalDatastoreType.OPERATIONAL, YangInstanceIdentifier.of(BmpMonitor.QNAME), parentNode);
         wTx.submit();
 
-        this.bmpApp = BmpMonitoringStationImpl.createBmpMonitorInstance(this.ribExtension, this.dispatcher, getDomBroker(),
-            this.tree, MONITOR_ID, inetAddress, null);
-
+        final BmpDeployerDependencies bmpDependecies = new BmpDeployerDependencies(getDataBroker(), getDomBroker(),
+            this.ribExtension, this.mappingService.getCodecFactory(), getSchemaContext(), this.clusterSSProv);
+        this.bmpApp = new BmpMonitoringStationImpl(bmpDependecies, this.dispatcher, MONITOR_ID, inetAddress, null);
         readDataOperational(getDataBroker(), BMP_II, monitor -> {
             assertEquals(1, monitor.getMonitor().size());
             final Monitor bmpMonitor = monitor.getMonitor().get(0);
@@ -419,10 +445,12 @@ public class BmpMonitorImplTest extends AbstractConcurrentDataBrokerTest {
 
     @Test
     public void deploySecondInstance() throws Exception {
-        final BmpMonitoringStation monitoringStation2 = BmpMonitoringStationImpl
-            .createBmpMonitorInstance(this.ribExtension, this.dispatcher, getDomBroker(), this.tree,
-                new MonitorId("monitor2"), new InetSocketAddress(InetAddresses.forString(MONITOR_LOCAL_ADDRESS_2),
-                    MONITOR_LOCAL_PORT),null);
+        final BmpDeployerDependencies bmpDependecies = new BmpDeployerDependencies(getDataBroker(), getDomBroker(),
+            this.ribExtension, this.mappingService.getCodecFactory(), getSchemaContext(), this.clusterSSProv2);
+
+        final BmpMonitoringStation monitoringStation2 = new BmpMonitoringStationImpl(bmpDependecies,
+            this.dispatcher, new MonitorId("monitor2"), new InetSocketAddress(InetAddresses.
+            forString(MONITOR_LOCAL_ADDRESS_2), MONITOR_LOCAL_PORT), null);
 
         readDataOperational(getDataBroker(), BMP_II, monitor -> {
             assertEquals(2, monitor.getMonitor().size());