Eliminate SchemaResourcesDTO
[netconf.git] / apps / netconf-topology-singleton / src / test / java / org / opendaylight / netconf / topology / singleton / impl / MountPointEndToEndTest.java
index d45a4aeb840f51af3a1a70c14b8acf89e092582e..b3989112f5ba458b757696ecebf3a2a989fed0f1 100644 (file)
@@ -18,7 +18,6 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
@@ -29,13 +28,11 @@ import akka.util.Timeout;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.util.concurrent.FluentFuture;
+import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.util.concurrent.SettableFuture;
 import com.typesafe.config.ConfigFactory;
-import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.GlobalEventExecutor;
 import java.io.File;
 import java.util.Iterator;
 import java.util.List;
@@ -55,25 +52,16 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
-import org.opendaylight.controller.cluster.ActorSystemProvider;
-import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
-import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.mdsal.binding.api.DataBroker;
-import org.opendaylight.mdsal.binding.api.DataObjectModification;
 import org.opendaylight.mdsal.binding.api.DataTreeIdentifier;
-import org.opendaylight.mdsal.binding.api.DataTreeModification;
 import org.opendaylight.mdsal.binding.api.ReadTransaction;
 import org.opendaylight.mdsal.binding.api.RpcProviderService;
-import org.opendaylight.mdsal.binding.api.Transaction;
 import org.opendaylight.mdsal.binding.api.TransactionChain;
-import org.opendaylight.mdsal.binding.api.TransactionChainListener;
 import org.opendaylight.mdsal.binding.api.WriteTransaction;
 import org.opendaylight.mdsal.binding.dom.adapter.test.AbstractConcurrentDataBrokerTest;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
 import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
-import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
-import org.opendaylight.mdsal.dom.api.DOMActionProviderService;
 import org.opendaylight.mdsal.dom.api.DOMActionService;
 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadOperations;
@@ -82,10 +70,8 @@ import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
 import org.opendaylight.mdsal.dom.api.DOMMountPointListener;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
-import org.opendaylight.mdsal.dom.api.DOMRpcAvailabilityListener;
 import org.opendaylight.mdsal.dom.api.DOMRpcIdentifier;
 import org.opendaylight.mdsal.dom.api.DOMRpcImplementation;
-import org.opendaylight.mdsal.dom.api.DOMRpcProviderService;
 import org.opendaylight.mdsal.dom.api.DOMRpcResult;
 import org.opendaylight.mdsal.dom.api.DOMRpcService;
 import org.opendaylight.mdsal.dom.api.DOMService;
@@ -93,37 +79,40 @@ import org.opendaylight.mdsal.dom.broker.DOMMountPointServiceImpl;
 import org.opendaylight.mdsal.dom.broker.DOMRpcRouter;
 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
-import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
-import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
-import org.opendaylight.mdsal.singleton.dom.impl.DOMClusterSingletonServiceProviderImpl;
-import org.opendaylight.netconf.client.NetconfClientDispatcher;
+import org.opendaylight.mdsal.eos.dom.simple.SimpleDOMEntityOwnershipService;
+import org.opendaylight.mdsal.singleton.api.ClusterSingletonServiceProvider;
+import org.opendaylight.mdsal.singleton.api.ServiceGroupIdentifier;
+import org.opendaylight.mdsal.singleton.impl.EOSClusterSingletonServiceProvider;
+import org.opendaylight.netconf.api.CapabilityURN;
+import org.opendaylight.netconf.client.NetconfClientFactory;
+import org.opendaylight.netconf.client.mdsal.NetconfDeviceCapabilities;
 import org.opendaylight.netconf.client.mdsal.NetconfDeviceSchema;
+import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
 import org.opendaylight.netconf.client.mdsal.api.DeviceActionFactory;
+import org.opendaylight.netconf.client.mdsal.api.NetconfSessionPreferences;
 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices;
 import org.opendaylight.netconf.client.mdsal.api.RemoteDeviceServices.Rpcs;
 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
+import org.opendaylight.netconf.client.mdsal.api.SslContextFactoryProvider;
 import org.opendaylight.netconf.client.mdsal.impl.DefaultSchemaResourceManager;
-import org.opendaylight.netconf.nettyutil.ReconnectFuture;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
-import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil;
+import org.opendaylight.netconf.common.NetconfTimer;
 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringRpcException;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
+import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactory;
+import org.opendaylight.netconf.topology.spi.NetconfClientConfigurationBuilderFactoryImpl;
+import org.opendaylight.netconf.topology.spi.NetconfNodeUtils;
+import org.opendaylight.netconf.topology.spi.NetconfTopologySchemaAssembler;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 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;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.ConnectionOper.ConnectionStatus;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPwUnencryptedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencryptedBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev171017.Keystore;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNode;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.network.topology.topology.topology.types.TopologyNetconf;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.ConfigBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.ConnectionOper.ConnectionStatus;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.LoginPwUnencryptedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev240120.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencryptedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.keystore.rev231109.Keystore;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev231121.NetconfNodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.GetTopInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.GetTopOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.PutTopInputBuilder;
@@ -137,14 +126,13 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
-import org.opendaylight.yangtools.rfc8528.data.api.MountPointContext;
-import org.opendaylight.yangtools.rfc8528.data.util.EmptyMountPointContext;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.util.concurrent.FluentFutures;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.common.Empty;
 import org.opendaylight.yangtools.yang.common.ErrorTag;
 import org.opendaylight.yangtools.yang.common.ErrorType;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -157,15 +145,17 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MountPointContext;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.api.source.SourceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.source.YangTextSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
+import org.opendaylight.yangtools.yang.model.spi.source.DelegatedYangTextSource;
 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -181,28 +171,35 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
     private static final String TOP_MODULE_NAME = "opendaylight-mdsal-list-test";
     private static final String ACTOR_SYSTEM_NAME = "test";
-    private static final String TOPOLOGY_ID = TopologyNetconf.QNAME.getLocalName();
+    private static final String TOPOLOGY_ID = NetconfNodeUtils.DEFAULT_TOPOLOGY_NAME;
     private static final @NonNull KeyedInstanceIdentifier<Node, NodeKey> NODE_INSTANCE_ID =
         NetconfTopologyUtils.createTopologyNodeListPath(new NodeKey(new NodeId("node-id")), TOPOLOGY_ID);
 
     private static final String TEST_ROOT_DIRECTORY = "test-cache-root";
     private static final String TEST_DEFAULT_SUBDIR = "test-schema";
 
-    @Mock private DOMRpcProviderService mockRpcProviderRegistry;
-    @Mock private RpcProviderService mockRpcProviderService;
-    @Mock private DOMActionProviderService mockActionProviderRegistry;
-    @Mock private NetconfClientDispatcher mockClientDispatcher;
-    @Mock private AAAEncryptionService mockEncryptionService;
-    @Mock private ThreadPool mockThreadPool;
-    @Mock private ScheduledThreadPool mockKeepaliveExecutor;
-    @Mock private DeviceActionFactory deviceActionFactory;
-
-    @Mock private ActorSystemProvider mockMasterActorSystemProvider;
-    @Mock private DOMMountPointListener masterMountPointListener;
+    @Mock
+    private RpcProviderService mockRpcProviderService;
+    @Mock
+    private Registration mockRpcReg;
+    @Mock
+    private NetconfClientFactory mockClientFactory;
+    @Mock
+    private AAAEncryptionService mockEncryptionService;
+    @Mock
+    private NetconfTimer mockTimer;
+    @Mock
+    private DeviceActionFactory deviceActionFactory;
+    @Mock
+    private CredentialProvider credentialProvider;
+    @Mock
+    private SslContextFactoryProvider sslHandlerFactoryProvider;
+    @Mock
+    private DOMMountPointListener masterMountPointListener;
     private final DOMMountPointService masterMountPointService = new DOMMountPointServiceImpl();
     private Rpcs.Normalized deviceRpcService;
 
-    private DOMClusterSingletonServiceProviderImpl masterClusterSingletonServiceProvider;
+    private EOSClusterSingletonServiceProvider masterClusterSingletonServiceProvider;
     private DataBroker masterDataBroker;
     private DOMDataBroker deviceDOMDataBroker;
     private ActorSystem masterSystem;
@@ -210,10 +207,12 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
     private volatile SettableFuture<MasterSalFacade> masterSalFacadeFuture = SettableFuture.create();
 
-    @Mock private ActorSystemProvider mockSlaveActorSystemProvider;
-    @Mock private ClusterSingletonServiceProvider mockSlaveClusterSingletonServiceProvider;
-    @Mock private ClusterSingletonServiceRegistration mockSlaveClusterSingletonServiceReg;
-    @Mock private DOMMountPointListener slaveMountPointListener;
+    @Mock
+    private ClusterSingletonServiceProvider mockSlaveClusterSingletonServiceProvider;
+    @Mock
+    private Registration mockSlaveClusterSingletonServiceReg;
+    @Mock
+    private DOMMountPointListener slaveMountPointListener;
     private final DOMMountPointService slaveMountPointService = new DOMMountPointServiceImpl();
     private DataBroker slaveDataBroker;
     private ActorSystem slaveSystem;
@@ -221,8 +220,7 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
     private final SettableFuture<NetconfTopologyContext> slaveNetconfTopologyContextFuture = SettableFuture.create();
     private TransactionChain slaveTxChain;
 
-    private final EventExecutor eventExecutor = GlobalEventExecutor.INSTANCE;
-    private final Config config = new ConfigBuilder().setWriteTransactionIdleTimeout(Uint16.ZERO).build();
+    private NetconfClientConfigurationBuilderFactory builderFactory;
     private EffectiveModelContext deviceSchemaContext;
     private YangModuleInfo topModuleInfo;
     private QName putTopRpcSchemaPath;
@@ -233,47 +231,43 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
     private final ContainerNode getTopInput = ImmutableNodes.containerNode(GetTopInput.QNAME);
 
     private SchemaResourceManager resourceManager;
+    private NetconfTopologySchemaAssembler schemaAssembler;
 
     @Before
     public void setUp() throws Exception {
         deleteCacheDir();
 
+        schemaAssembler = new NetconfTopologySchemaAssembler(1, 1, 0, TimeUnit.SECONDS);
+
         resourceManager = new DefaultSchemaResourceManager(new DefaultYangParserFactory(), TEST_ROOT_DIRECTORY,
             TEST_DEFAULT_SUBDIR);
 
-        topModuleInfo = BindingReflections.getModuleInfo(Top.class);
+        topModuleInfo = BindingRuntimeHelpers.getYangModuleInfo(Top.class);
 
         deviceSchemaContext = BindingRuntimeHelpers.createEffectiveModel(Top.class);
 
-        final var router = new DOMRpcRouter(FixedDOMSchemaService.of(deviceSchemaContext));
+        final var router = new DOMRpcRouter(new FixedDOMSchemaService(deviceSchemaContext));
 
         putTopRpcSchemaPath = findRpcDefinition("put-top").getQName();
         getTopRpcSchemaPath = findRpcDefinition("get-top").getQName();
 
-        router.getRpcProviderService().registerRpcImplementation(topRpcImplementation,
+        router.rpcProviderService().registerRpcImplementation(topRpcImplementation,
                 DOMRpcIdentifier.create(putTopRpcSchemaPath), DOMRpcIdentifier.create(getTopRpcSchemaPath));
 
-        final var rpcService = router.getRpcService();
-        deviceRpcService = new Rpcs.Normalized() {
-            @Override
-            public ListenableFuture<? extends DOMRpcResult> invokeRpc(final QName type, final ContainerNode input) {
-                return rpcService.invokeRpc(type, input);
-            }
+        final var rpcService = router.rpcService();
+        deviceRpcService = () -> rpcService;
 
-            @Override
-            public <T extends DOMRpcAvailabilityListener> ListenerRegistration<T> registerRpcListener(
-                    final T listener) {
-                return rpcService.registerRpcListener(listener);
-            }
-        };
+        builderFactory = new NetconfClientConfigurationBuilderFactoryImpl(mockEncryptionService, credentialProvider,
+            sslHandlerFactoryProvider);
+
+        doReturn(mockRpcReg).when(mockRpcProviderService).registerRpcImplementations(any());
 
         setupMaster();
 
         setupSlave();
 
         yangNodeInstanceId = bindingToNormalized.toYangInstanceIdentifier(NODE_INSTANCE_ID);
-
-        doReturn(mock(ReconnectFuture.class)).when(mockClientDispatcher).createReconnectingClient(any());
+        doReturn(mock(ListenableFuture.class)).when(mockClientFactory).createClient(any());
 
         LOG.info("****** Setup complete");
     }
@@ -287,6 +281,7 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         deleteCacheDir();
         TestKit.shutdownActorSystem(slaveSystem, true);
         TestKit.shutdownActorSystem(masterSystem, true);
+        schemaAssembler.close();
     }
 
     private void setupMaster() throws Exception {
@@ -297,48 +292,40 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
         masterSystem = ActorSystem.create(ACTOR_SYSTEM_NAME, ConfigFactory.load().getConfig("Master"));
 
-        masterClusterSingletonServiceProvider = new DOMClusterSingletonServiceProviderImpl();
-        masterClusterSingletonServiceProvider.initializeProvider();
-
-        doReturn(masterSystem).when(mockMasterActorSystemProvider).getActorSystem();
-
-        doReturn(MoreExecutors.newDirectExecutorService()).when(mockThreadPool).getExecutor();
+        masterClusterSingletonServiceProvider = new EOSClusterSingletonServiceProvider(
+            new SimpleDOMEntityOwnershipService());
 
         final var resources =  resourceManager.getSchemaResources(TEST_DEFAULT_SUBDIR, "test");
-        resources.getSchemaRegistry().registerSchemaSource(
-            id -> Futures.immediateFuture(YangTextSchemaSource.delegateForByteSource(id,
-                    topModuleInfo.getYangTextByteSource())),
+        resources.registry().registerSchemaSource(
+            id -> Futures.immediateFuture(new DelegatedYangTextSource(id, topModuleInfo.getYangTextCharSource())),
             PotentialSchemaSource.create(new SourceIdentifier(TOP_MODULE_NAME,
                     topModuleInfo.getName().getRevision().map(Revision::toString).orElse(null)),
-                YangTextSchemaSource.class, 1));
+                YangTextSource.class, 1));
 
         masterNetconfTopologyManager = new NetconfTopologyManager(BASE_SCHEMAS, masterDataBroker,
-                mockRpcProviderRegistry, mockActionProviderRegistry, masterClusterSingletonServiceProvider,
-                mockKeepaliveExecutor, mockThreadPool, mockMasterActorSystemProvider, eventExecutor,
-                mockClientDispatcher, TOPOLOGY_ID, config, masterMountPointService, mockEncryptionService,
-                mockRpcProviderService, deviceActionFactory, resourceManager) {
+                masterClusterSingletonServiceProvider, mockTimer, schemaAssembler, masterSystem,
+                mockClientFactory, masterMountPointService, mockEncryptionService, mockRpcProviderService,
+                deviceActionFactory, resourceManager, builderFactory, TOPOLOGY_ID, Uint16.ZERO) {
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                     final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
                     final DeviceActionFactory deviceActionFact) {
                 final var context = super.newNetconfTopologyContext(setup, serviceGroupIdent, actorResponseWaitTime,
                     deviceActionFact);
-
                 final var spiedContext = spy(context);
+                final var spiedSingleton = spy(context.getTopologySingleton());
                 doAnswer(invocation -> {
                     final var spiedFacade = (MasterSalFacade) spy(invocation.callRealMethod());
                     doReturn(deviceDOMDataBroker).when(spiedFacade)
                         .newDeviceDataBroker(any(MountPointContext.class), any(NetconfSessionPreferences.class));
                     masterSalFacadeFuture.set(spiedFacade);
                     return spiedFacade;
-                }).when(spiedContext).newMasterSalFacade();
-
+                }).when(spiedSingleton).createSalFacade(any(boolean.class));
+                doReturn(spiedSingleton).when(spiedContext).getTopologySingleton();
                 return spiedContext;
             }
         };
 
-        masterNetconfTopologyManager.init();
-
         verifyTopologyNodesCreated(masterDataBroker);
     }
 
@@ -348,16 +335,13 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
         slaveSystem = ActorSystem.create(ACTOR_SYSTEM_NAME, ConfigFactory.load().getConfig("Slave"));
 
-        doReturn(slaveSystem).when(mockSlaveActorSystemProvider).getActorSystem();
-
         doReturn(mockSlaveClusterSingletonServiceReg).when(mockSlaveClusterSingletonServiceProvider)
                 .registerClusterSingletonService(any());
 
-        slaveNetconfTopologyManager = new NetconfTopologyManager(BASE_SCHEMAS, slaveDataBroker, mockRpcProviderRegistry,
-            mockActionProviderRegistry, mockSlaveClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
-                mockSlaveActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
-                slaveMountPointService, mockEncryptionService, mockRpcProviderService, deviceActionFactory,
-                resourceManager) {
+        slaveNetconfTopologyManager = new NetconfTopologyManager(BASE_SCHEMAS, slaveDataBroker,
+                mockSlaveClusterSingletonServiceProvider, mockTimer, schemaAssembler, slaveSystem,
+                mockClientFactory, slaveMountPointService, mockEncryptionService, mockRpcProviderService,
+                deviceActionFactory, resourceManager, builderFactory, TOPOLOGY_ID, Uint16.ZERO) {
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
@@ -370,18 +354,17 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
             }
         };
 
-        slaveNetconfTopologyManager.init();
-
         verifyTopologyNodesCreated(slaveDataBroker);
 
-        slaveTxChain = slaveDataBroker.createTransactionChain(new TransactionChainListener() {
+        slaveTxChain = slaveDataBroker.createTransactionChain();
+        slaveTxChain.addCallback(new FutureCallback<Empty>() {
             @Override
-            public void onTransactionChainSuccessful(final TransactionChain chain) {
+            public void onSuccess(final Empty result) {
+                // No-op
             }
 
             @Override
-            public void onTransactionChainFailed(final TransactionChain chain, final Transaction transaction,
-                    final Throwable cause) {
+            public void onFailure(final Throwable cause) {
                 LOG.error("Slave transaction chain failed", cause);
             }
         });
@@ -407,9 +390,8 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
         final var masterSalFacade = masterSalFacadeFuture.get(5, TimeUnit.SECONDS);
         masterSalFacade.onDeviceConnected(new NetconfDeviceSchema(NetconfDeviceCapabilities.empty(),
-            new EmptyMountPointContext(deviceSchemaContext)),
-            NetconfSessionPreferences.fromStrings(
-                List.of(NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString())),
+            MountPointContext.of(deviceSchemaContext)),
+            NetconfSessionPreferences.fromStrings(List.of(CapabilityURN.CANDIDATE)),
             new RemoteDeviceServices(deviceRpcService, null));
 
         final var masterMountPoint = awaitMountPoint(masterMountPointService);
@@ -434,16 +416,16 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         // Since the master and slave use separate DataBrokers we need to copy the master's oper node to the slave.
         // This is essentially what happens in a clustered environment but we'll use a DTCL here.
 
-        masterDataBroker.registerDataTreeChangeListener(
-            DataTreeIdentifier.create(LogicalDatastoreType.OPERATIONAL, NODE_INSTANCE_ID), changes -> {
+        masterDataBroker.registerTreeChangeListener(
+            DataTreeIdentifier.of(LogicalDatastoreType.OPERATIONAL, NODE_INSTANCE_ID), changes -> {
                 final WriteTransaction slaveTx = slaveTxChain.newWriteOnlyTransaction();
-                for (DataTreeModification<Node> dataTreeModification : changes) {
-                    DataObjectModification<Node> rootNode = dataTreeModification.getRootNode();
-                    InstanceIdentifier<Node> path = dataTreeModification.getRootPath().getRootIdentifier();
-                    switch (rootNode.getModificationType()) {
+                for (var dataTreeModification : changes) {
+                    var rootNode = dataTreeModification.getRootNode();
+                    var path = dataTreeModification.getRootPath().path();
+                    switch (rootNode.modificationType()) {
                         case WRITE:
                         case SUBTREE_MODIFIED:
-                            slaveTx.merge(LogicalDatastoreType.OPERATIONAL, path, rootNode.getDataAfter());
+                            slaveTx.merge(LogicalDatastoreType.OPERATIONAL, path, rootNode.dataAfter());
                             break;
                         case DELETE:
                             slaveTx.delete(LogicalDatastoreType.OPERATIONAL, path);
@@ -458,10 +440,6 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
 
         DOMMountPoint slaveMountPoint = awaitMountPoint(slaveMountPointService);
 
-        final NetconfTopologyContext slaveNetconfTopologyContext =
-                slaveNetconfTopologyContextFuture.get(5, TimeUnit.SECONDS);
-        verify(slaveNetconfTopologyContext, never()).newMasterSalFacade();
-
         LOG.info("****** Testing slave DOMDataBroker operations");
 
         testDOMDataBrokerOperations(getDOMDataBroker(slaveMountPoint));
@@ -483,10 +461,10 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         verify(masterMountPointListener, timeout(5000)).onMountPointRemoved(yangNodeInstanceId);
 
         final var masterSalFacade = masterSalFacadeFuture.get(5, TimeUnit.SECONDS);
-        masterSalFacade.onDeviceConnected(new NetconfDeviceSchema(NetconfDeviceCapabilities.empty(),
-            new EmptyMountPointContext(deviceSchemaContext)), NetconfSessionPreferences.fromStrings(List.of(
-                    NetconfMessageTransformUtil.NETCONF_CANDIDATE_URI.toString())),
-                new RemoteDeviceServices(deviceRpcService, null));
+        masterSalFacade.onDeviceConnected(
+            new NetconfDeviceSchema(NetconfDeviceCapabilities.empty(), MountPointContext.of(deviceSchemaContext)),
+            NetconfSessionPreferences.fromStrings(List.of(CapabilityURN.CANDIDATE)),
+            new RemoteDeviceServices(deviceRpcService, null));
 
         verify(masterMountPointListener, timeout(5000)).onMountPointCreated(yangNodeInstanceId);
 
@@ -685,10 +663,11 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         final var dataBrokerTest = new AbstractConcurrentDataBrokerTest(true) {
             @Override
             protected Set<YangModuleInfo> getModuleInfos() {
-                return Set.of(BindingReflections.getModuleInfo(NetconfNode.class),
-                        BindingReflections.getModuleInfo(NetworkTopology.class),
-                        BindingReflections.getModuleInfo(Keystore.class),
-                        topModuleInfo);
+                return Set.of(
+                    BindingRuntimeHelpers.getYangModuleInfo(NetconfNode.class),
+                    BindingRuntimeHelpers.getYangModuleInfo(NetworkTopology.class),
+                    BindingRuntimeHelpers.getYangModuleInfo(Keystore.class),
+                    topModuleInfo);
             }
         };
 
@@ -716,8 +695,8 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         return getMountPointService(mountPoint, DOMActionService.class);
     }
 
-    private static <T extends DOMService> T getMountPointService(final DOMMountPoint mountPoint,
-            final Class<T> serviceClass) {
+    private static <T extends DOMService<T, E>, E extends DOMService.Extension<T, E>> T getMountPointService(
+            final DOMMountPoint mountPoint, final Class<T> serviceClass) {
         return mountPoint.getService(serviceClass).orElseThrow();
     }
 
@@ -743,7 +722,7 @@ public class MountPointEndToEndTest extends AbstractBaseSchemasTest {
         return rpcDefinition;
     }
 
-    private static class TopDOMRpcImplementation implements DOMRpcImplementation {
+    private static final class TopDOMRpcImplementation implements DOMRpcImplementation {
         private volatile SettableFuture<Entry<DOMRpcIdentifier, NormalizedNode>> rpcInvokedFuture;
         private volatile ListenableFuture<DOMRpcResult> returnFuture;