From d5d6467f85dab8256e5ef16a975aaa20caec891b Mon Sep 17 00:00:00 2001 From: "tobias.pobocik" Date: Mon, 13 Jul 2020 10:46:42 +0200 Subject: [PATCH] Add session-id to the operational datastore MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Expose non-zero uint32 session-id provided by the device in the HELLO-MESSAGE via operational datastore. When device is disconnected null is used to indicate a non-NETCONF entity session. Session id can be used to retrieve session-specific info of the device. JIRA: NETCONF-710 Change-Id: I1995e825cf32462232e164727a469a7b47d3acd0 Signed-off-by: Tibor Král Signed-off-by: tobias.pobocik Signed-off-by: Ivan Hrasko Signed-off-by: Peter Suna --- .../singleton/impl/MasterSalFacade.java | 5 +- .../spi/NetconfDeviceTopologyAdapter.java | 19 ++++--- .../topology/spi/NetconfNodeUtils.java | 6 +-- .../spi/NetconfTopologyDeviceSalFacade.java | 5 +- ...fDeficeTopologyAdapterIntegrationTest.java | 3 +- .../spi/NetconfDeviceTopologyAdapterTest.java | 3 +- .../listener/NetconfSessionPreferences.java | 29 +++++++---- .../src/main/yang/odl-netconf-device.yang | 7 +++ .../NetconfDeviceCommunicatorTest.java | 51 ++++++++++--------- 9 files changed, 75 insertions(+), 53 deletions(-) diff --git a/apps/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java b/apps/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java index 517a0d22e0..81f49e10ca 100644 --- a/apps/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java +++ b/apps/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/MasterSalFacade.java @@ -105,7 +105,7 @@ class MasterSalFacade implements RemoteDeviceHandler, AutoCloseable { @Override public void onDeviceDisconnected() { LOG.info("Device {} disconnected - unregistering master mount point", id); - datastoreAdapter.updateDeviceData(false, NetconfDeviceCapabilities.empty()); + datastoreAdapter.updateDeviceData(false, NetconfDeviceCapabilities.empty(), null); mount.onDeviceDisconnected(); } @@ -173,6 +173,7 @@ class MasterSalFacade implements RemoteDeviceHandler, AutoCloseable { private void updateDeviceData() { final String masterAddress = Cluster.get(actorSystem).selfAddress().toString(); LOG.debug("{}: updateDeviceData with master address {}", id, masterAddress); - datastoreAdapter.updateClusteredDeviceData(true, masterAddress, currentSchema.capabilities()); + datastoreAdapter.updateClusteredDeviceData(true, masterAddress, currentSchema.capabilities(), + netconfSessionPreferences.sessionId()); } } diff --git a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapter.java b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapter.java index ad3ba42a02..b5e2714d4c 100644 --- a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapter.java +++ b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapter.java @@ -14,7 +14,6 @@ import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; import org.eclipse.jdt.annotation.NonNull; import org.opendaylight.mdsal.binding.api.DataBroker; import org.opendaylight.mdsal.binding.api.Transaction; @@ -44,6 +43,7 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.common.Empty; import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -88,14 +88,15 @@ public final class NetconfDeviceTopologyAdapter implements TransactionChainListe return nodePath().augmentation(NetconfNode.class); } - public void updateDeviceData(final boolean up, final NetconfDeviceCapabilities capabilities) { + public void updateDeviceData(final boolean up, final NetconfDeviceCapabilities capabilities, + final Uint32 sessionId) { final WriteTransaction writeTx = txChain.newWriteOnlyTransaction(); LOG.trace("{}: Update device state transaction {} merging operational data started.", id, writeTx.getIdentifier()); // FIXME: this needs to be tied together with node's operational existence writeTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, netconfNodePath(), - newNetconfNodeBuilder(up, capabilities).build()); + newNetconfNodeBuilder(up, capabilities, sessionId).build()); LOG.trace("{}: Update device state transaction {} merging operational data ended.", id, writeTx.getIdentifier()); @@ -103,12 +104,12 @@ public final class NetconfDeviceTopologyAdapter implements TransactionChainListe } public void updateClusteredDeviceData(final boolean up, final String masterAddress, - final NetconfDeviceCapabilities capabilities) { + final NetconfDeviceCapabilities capabilities, final Uint32 sessionId) { final WriteTransaction writeTx = txChain.newWriteOnlyTransaction(); LOG.trace("{}: Update device state transaction {} merging operational data started.", id, writeTx.getIdentifier()); writeTx.mergeParentStructurePut(LogicalDatastoreType.OPERATIONAL, netconfNodePath(), - newNetconfNodeBuilder(up, capabilities) + newNetconfNodeBuilder(up, capabilities, sessionId) .setClusteredConnectionStatus(new ClusteredConnectionStatusBuilder() .setNetconfMasterNode(masterAddress) .build()) @@ -156,7 +157,8 @@ public final class NetconfDeviceTopologyAdapter implements TransactionChainListe commitTransaction(writeTx, "update-failed-device"); } - private NetconfNodeBuilder newNetconfNodeBuilder(final boolean up, final NetconfDeviceCapabilities capabilities) { + private NetconfNodeBuilder newNetconfNodeBuilder(final boolean up, final NetconfDeviceCapabilities capabilities, + final Uint32 sessionId) { return new NetconfNodeBuilder() .setHost(id.host()) .setPort(new PortNumber(Uint16.valueOf(id.address().getPort()))) @@ -174,8 +176,9 @@ public final class NetconfDeviceTopologyAdapter implements TransactionChainListe .setCapability(unresolved.getKey().toString()) .setFailureReason(unresolved.getValue()) .build()) - .collect(Collectors.toUnmodifiableList())) - .build()); + .toList()) + .build()) + .setSessionId(sessionId); } private void commitTransaction(final WriteTransaction transaction, final String txType) { diff --git a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfNodeUtils.java b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfNodeUtils.java index ce6b1132c0..2326567b31 100644 --- a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfNodeUtils.java +++ b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfNodeUtils.java @@ -103,7 +103,7 @@ public final class NetconfNodeUtils { //non-module capabilities should not exist in yang module capabilities final var sessionPreferences = NetconfSessionPreferences.fromStrings(capabilities, - CapabilityOrigin.DeviceAdvertised); + CapabilityOrigin.DeviceAdvertised, node.getSessionId()); final var nonModulePrefs = sessionPreferences.nonModuleCaps(); if (!nonModulePrefs.isEmpty()) { throw new IllegalArgumentException("List yang-module-capabilities/capability should contain only module " @@ -121,8 +121,8 @@ public final class NetconfNodeUtils { // FIXME: UserPreferences is constructor parameter of NetconfDeviceCommunicator and NetconfSessionPreferences // are created in NetconfDeviceCommunicator#onSessionUp from session. What are we doing here? // IMO we should rework UserPreferences and NetconfSessionPreferences and this method. - return new UserPreferences(NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined), - overrideYangModuleCaps, overrideNonModuleCaps); + return new UserPreferences(NetconfSessionPreferences.fromStrings(capabilities, CapabilityOrigin.UserDefined, + node.getSessionId()), overrideYangModuleCaps, overrideNonModuleCaps); } @Deprecated(forRemoval = true) diff --git a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfTopologyDeviceSalFacade.java b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfTopologyDeviceSalFacade.java index 5c7f118703..c258b629a6 100644 --- a/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfTopologyDeviceSalFacade.java +++ b/apps/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/NetconfTopologyDeviceSalFacade.java @@ -32,13 +32,12 @@ public class NetconfTopologyDeviceSalFacade extends NetconfDeviceSalFacade { public synchronized void onDeviceConnected(final NetconfDeviceSchema deviceSchema, final NetconfSessionPreferences sessionPreferences, final RemoteDeviceServices services) { super.onDeviceConnected(deviceSchema, sessionPreferences, services); - datastoreAdapter.updateDeviceData(true, deviceSchema.capabilities()); - + datastoreAdapter.updateDeviceData(true, deviceSchema.capabilities(), sessionPreferences.sessionId()); } @Override public synchronized void onDeviceDisconnected() { - datastoreAdapter.updateDeviceData(false, NetconfDeviceCapabilities.empty()); + datastoreAdapter.updateDeviceData(false, NetconfDeviceCapabilities.empty(), null); super.onDeviceDisconnected(); } diff --git a/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeficeTopologyAdapterIntegrationTest.java b/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeficeTopologyAdapterIntegrationTest.java index d3677ceadd..a1a4fb0c59 100644 --- a/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeficeTopologyAdapterIntegrationTest.java +++ b/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeficeTopologyAdapterIntegrationTest.java @@ -38,6 +38,7 @@ 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.NodeKey; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Uint32; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; @@ -114,7 +115,7 @@ public class NetconfDeficeTopologyAdapterIntegrationTest { wtx.put(LogicalDatastoreType.OPERATIONAL, pathToAugmentedLeaf, augmentNode); wtx.commit().get(5, TimeUnit.SECONDS); - adapter.updateDeviceData(true, NetconfDeviceCapabilities.empty()); + adapter.updateDeviceData(true, NetconfDeviceCapabilities.empty(), Uint32.ONE); assertEquals(Optional.of(dataTestId), domDataBroker.newReadOnlyTransaction() .read(LogicalDatastoreType.OPERATIONAL, pathToAugmentedLeaf) diff --git a/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapterTest.java b/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapterTest.java index c86bb3c8e6..8fc65fa2d5 100644 --- a/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapterTest.java +++ b/apps/netconf-topology/src/test/java/org/opendaylight/netconf/topology/spi/NetconfDeviceTopologyAdapterTest.java @@ -36,6 +36,7 @@ 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.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; +import org.opendaylight.yangtools.yang.common.Uint32; @RunWith(MockitoJUnitRunner.StrictStubs.class) public class NetconfDeviceTopologyAdapterTest { @@ -85,7 +86,7 @@ public class NetconfDeviceTopologyAdapterTest { @Test public void testDeviceUpdate() throws Exception { - adapter.updateDeviceData(true, NetconfDeviceCapabilities.empty()); + adapter.updateDeviceData(true, NetconfDeviceCapabilities.empty(), Uint32.ONE); verify(mockChain, times(2)).newWriteOnlyTransaction(); verify(mockTx, times(1)).put(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(Node.class)); diff --git a/plugins/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfSessionPreferences.java b/plugins/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfSessionPreferences.java index 32aa0a3a68..ff29a18686 100644 --- a/plugins/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfSessionPreferences.java +++ b/plugins/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfSessionPreferences.java @@ -26,6 +26,7 @@ import org.opendaylight.netconf.client.NetconfClientSession; import org.opendaylight.netconf.sal.connect.netconf.util.NetconfMessageTransformUtil; import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev221225.connection.oper.available.capabilities.AvailableCapability.CapabilityOrigin; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Uint32; import org.opendaylight.yangtools.yang.common.XMLNamespace; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,7 +34,8 @@ import org.slf4j.LoggerFactory; // FIXME: propagate to API with immutable semantics public record NetconfSessionPreferences( @NonNull ImmutableMap nonModuleCaps, - @NonNull ImmutableMap moduleBasedCaps) { + @NonNull ImmutableMap moduleBasedCaps, + @Nullable Uint32 sessionId) { private static final Logger LOG = LoggerFactory.getLogger(NetconfSessionPreferences.class); private static final ParameterMatcher MODULE_PARAM = new ParameterMatcher("module="); private static final ParameterMatcher REVISION_PARAM = new ParameterMatcher("revision="); @@ -46,17 +48,17 @@ public record NetconfSessionPreferences( } public static @NonNull NetconfSessionPreferences fromNetconfSession(final NetconfClientSession session) { - return fromStrings(session.getServerCapabilities()); + return fromStrings(session.getServerCapabilities(), CapabilityOrigin.DeviceAdvertised, + Uint32.valueOf(session.getSessionId())); } @VisibleForTesting public static @NonNull NetconfSessionPreferences fromStrings(final Collection capabilities) { - // we do not know origin of capabilities from only Strings, so we set it to default value - return fromStrings(capabilities, CapabilityOrigin.DeviceAdvertised); + return fromStrings(capabilities, CapabilityOrigin.DeviceAdvertised, null); } public static @NonNull NetconfSessionPreferences fromStrings(final Collection capabilities, - final CapabilityOrigin capabilityOrigin) { + final CapabilityOrigin capabilityOrigin, final Uint32 sessionId) { final var moduleBasedCaps = new HashMap(); final var nonModuleCaps = new HashMap(); @@ -104,7 +106,8 @@ public record NetconfSessionPreferences( cachedQName(namespace, moduleName), capabilityOrigin); } - return new NetconfSessionPreferences(ImmutableMap.copyOf(nonModuleCaps), ImmutableMap.copyOf(moduleBasedCaps)); + return new NetconfSessionPreferences(ImmutableMap.copyOf(nonModuleCaps), ImmutableMap.copyOf(moduleBasedCaps), + sessionId); } public @Nullable CapabilityOrigin capabilityOrigin(final QName capability) { @@ -180,7 +183,8 @@ public record NetconfSessionPreferences( + netconfSessionModuleCapabilities.moduleBasedCaps.size()); mergedCaps.putAll(moduleBasedCaps); mergedCaps.putAll(netconfSessionModuleCapabilities.moduleBasedCaps); - return new NetconfSessionPreferences(nonModuleCaps, ImmutableMap.copyOf(mergedCaps)); + return new NetconfSessionPreferences(nonModuleCaps, ImmutableMap.copyOf(mergedCaps), + netconfSessionModuleCapabilities.sessionId()); } /** @@ -190,11 +194,12 @@ public record NetconfSessionPreferences( * @return new instance of preferences with replaced module-based capabilities */ public NetconfSessionPreferences replaceModuleCaps(final NetconfSessionPreferences netconfSessionPreferences) { - return new NetconfSessionPreferences(nonModuleCaps, netconfSessionPreferences.moduleBasedCaps); + return new NetconfSessionPreferences(nonModuleCaps, netconfSessionPreferences.moduleBasedCaps, + netconfSessionPreferences.sessionId()); } public NetconfSessionPreferences replaceModuleCaps(final Map newModuleBasedCaps) { - return new NetconfSessionPreferences(nonModuleCaps, ImmutableMap.copyOf(newModuleBasedCaps)); + return new NetconfSessionPreferences(nonModuleCaps, ImmutableMap.copyOf(newModuleBasedCaps), sessionId()); } /** @@ -209,7 +214,8 @@ public record NetconfSessionPreferences( nonModuleCaps.size() + netconfSessionNonModuleCapabilities.nonModuleCaps.size()); mergedCaps.putAll(nonModuleCaps); mergedCaps.putAll(netconfSessionNonModuleCapabilities.nonModuleCaps); - return new NetconfSessionPreferences(ImmutableMap.copyOf(mergedCaps), moduleBasedCaps); + return new NetconfSessionPreferences(ImmutableMap.copyOf(mergedCaps), moduleBasedCaps, + netconfSessionNonModuleCapabilities.sessionId()); } /** @@ -219,7 +225,8 @@ public record NetconfSessionPreferences( * @return new instance of preferences with replaced non-module based capabilities */ public NetconfSessionPreferences replaceNonModuleCaps(final NetconfSessionPreferences netconfSessionPreferences) { - return new NetconfSessionPreferences(netconfSessionPreferences.nonModuleCaps, moduleBasedCaps); + return new NetconfSessionPreferences(netconfSessionPreferences.nonModuleCaps, moduleBasedCaps, + netconfSessionPreferences.sessionId()); } private static QName cachedQName(final String namespace, final String revision, final String moduleName) { diff --git a/plugins/sal-netconf-connector/src/main/yang/odl-netconf-device.yang b/plugins/sal-netconf-connector/src/main/yang/odl-netconf-device.yang index 4c676548f7..857dcaf7ce 100644 --- a/plugins/sal-netconf-connector/src/main/yang/odl-netconf-device.yang +++ b/plugins/sal-netconf-connector/src/main/yang/odl-netconf-device.yang @@ -219,6 +219,13 @@ module odl-netconf-device { } grouping connection-oper { + leaf session-id { + config false; + type uint32 { + range "1..max"; + } + } + leaf connection-status { config false; type enumeration { diff --git a/plugins/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java b/plugins/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java index 20f231c100..d60a188aec 100644 --- a/plugins/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java +++ b/plugins/sal-netconf-connector/src/test/java/org/opendaylight/netconf/sal/connect/netconf/listener/NetconfDeviceCommunicatorTest.java @@ -27,6 +27,7 @@ import static org.opendaylight.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARA import com.google.common.base.CharMatcher; import com.google.common.base.Strings; import com.google.common.util.concurrent.ListenableFuture; +import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; @@ -38,7 +39,6 @@ import io.netty.util.concurrent.GlobalEventExecutor; import java.io.ByteArrayInputStream; import java.net.InetSocketAddress; import java.util.ArrayList; -import java.util.Collections; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; @@ -55,6 +55,7 @@ import org.opendaylight.netconf.api.NetconfTerminationReason; import org.opendaylight.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.netconf.client.NetconfClientDispatcherImpl; import org.opendaylight.netconf.client.NetconfClientSession; +import org.opendaylight.netconf.client.NetconfClientSessionListener; import org.opendaylight.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration; import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder; @@ -71,6 +72,7 @@ import org.opendaylight.yangtools.yang.common.ErrorType; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.RpcError; import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.common.Uint32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -80,26 +82,26 @@ import org.w3c.dom.Element; public class NetconfDeviceCommunicatorTest { private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceCommunicatorTest.class); - - @Mock - NetconfClientSession mockSession; + private static final Uint32 SESSION_ID = Uint32.ONE; @Mock RemoteDevice mockDevice; - NetconfDeviceCommunicator communicator; + private NetconfClientSession spySession; + private NetconfDeviceCommunicator communicator; @Before public void setUp() throws Exception { communicator = new NetconfDeviceCommunicator( new RemoteDeviceId("test", InetSocketAddress.createUnresolved("localhost", 22)), mockDevice, 10); + spySession = spy(new NetconfClientSession(mock(NetconfClientSessionListener.class), mock(Channel.class), + SESSION_ID.toJava(), Set.of())); } void setupSession() { - doReturn(Collections.emptySet()).when(mockSession).getServerCapabilities(); doNothing().when(mockDevice).onRemoteSessionUp(any(NetconfSessionPreferences.class), any(NetconfDeviceCommunicator.class)); - communicator.onSessionUp(mockSession); + communicator.onSessionUp(spySession); } private ListenableFuture> sendRequest() throws Exception { @@ -118,7 +120,7 @@ public class NetconfDeviceCommunicatorTest { ChannelFuture mockChannelFuture = mock(ChannelFuture.class); doReturn(mockChannelFuture).when(mockChannelFuture) .addListener(any(GenericFutureListener.class)); - doReturn(mockChannelFuture).when(mockSession).sendMessage(same(message)); + doReturn(mockChannelFuture).when(spySession).sendMessage(same(message)); ListenableFuture> resultFuture = communicator.sendRequest(message, QName.create("", "mockRpc")); @@ -135,14 +137,14 @@ public class NetconfDeviceCommunicatorTest { NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString(), NetconfMessageTransformUtil.IETF_NETCONF_MONITORING.getNamespace().toString(), testCapability); - doReturn(serverCapabilities).when(mockSession).getServerCapabilities(); + doReturn(serverCapabilities).when(spySession).getServerCapabilities(); final var netconfSessionPreferences = ArgumentCaptor.forClass(NetconfSessionPreferences.class); doNothing().when(mockDevice).onRemoteSessionUp(netconfSessionPreferences.capture(), eq(communicator)); - communicator.onSessionUp(mockSession); + communicator.onSessionUp(spySession); - verify(mockSession).getServerCapabilities(); + verify(spySession).getServerCapabilities(); verify(mockDevice).onRemoteSessionUp(netconfSessionPreferences.capture(), eq(communicator)); NetconfSessionPreferences actualCapabilites = netconfSessionPreferences.getValue(); @@ -153,6 +155,7 @@ public class NetconfDeviceCommunicatorTest { actualCapabilites.moduleBasedCaps().keySet()); assertTrue(actualCapabilites.isRollbackSupported()); assertTrue(actualCapabilites.isMonitoringSupported()); + assertEquals(SESSION_ID, actualCapabilites.sessionId()); } @SuppressWarnings("unchecked") @@ -165,7 +168,7 @@ public class NetconfDeviceCommunicatorTest { doNothing().when(mockDevice).onRemoteSessionDown(); - communicator.onSessionDown(mockSession, new Exception("mock ex")); + communicator.onSessionDown(spySession, new Exception("mock ex")); verifyErrorRpcResult(resultFuture1.get(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED); verifyErrorRpcResult(resultFuture2.get(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED); @@ -174,7 +177,7 @@ public class NetconfDeviceCommunicatorTest { reset(mockDevice); - communicator.onSessionDown(mockSession, new Exception("mock ex")); + communicator.onSessionDown(spySession, new Exception("mock ex")); verify(mockDevice, never()).onRemoteSessionDown(); } @@ -189,7 +192,7 @@ public class NetconfDeviceCommunicatorTest { String reasonText = "testing terminate"; NetconfTerminationReason reason = new NetconfTerminationReason(reasonText); - communicator.onSessionTerminated(mockSession, reason); + communicator.onSessionTerminated(spySession, reason); RpcError rpcError = verifyErrorRpcResult(resultFuture.get(), ErrorType.TRANSPORT, ErrorTag.OPERATION_FAILED); assertEquals("RpcError message", reasonText, rpcError.getMessage()); @@ -216,11 +219,11 @@ public class NetconfDeviceCommunicatorTest { ChannelFuture mockChannelFuture = mock(ChannelFuture.class); doReturn(mockChannelFuture).when(mockChannelFuture).addListener(futureListener.capture()); - doReturn(mockChannelFuture).when(mockSession).sendMessage(same(message)); + doReturn(mockChannelFuture).when(spySession).sendMessage(same(message)); ListenableFuture> resultFuture = communicator.sendRequest(message, rpc); - verify(mockSession).sendMessage(same(message)); + verify(spySession).sendMessage(same(message)); assertNotNull("ListenableFuture is null", resultFuture); @@ -278,7 +281,7 @@ public class NetconfDeviceCommunicatorTest { ChannelFuture mockChannelFuture = mock(ChannelFuture.class); doReturn(mockChannelFuture).when(mockChannelFuture).addListener(futureListener.capture()); - doReturn(mockChannelFuture).when(mockSession).sendMessage(same(message)); + doReturn(mockChannelFuture).when(spySession).sendMessage(same(message)); ListenableFuture> resultFuture = communicator.sendRequest(message, rpc); @@ -315,7 +318,7 @@ public class NetconfDeviceCommunicatorTest { ListenableFuture> resultFuture3 = sendRequest(messageID3, true); //response messages 1,2 are omitted - communicator.onMessage(mockSession, createSuccessResponseMessage(messageID3)); + communicator.onMessage(spySession, createSuccessResponseMessage(messageID3)); verifyResponseMessage(resultFuture3.get(), messageID3); } @@ -330,8 +333,8 @@ public class NetconfDeviceCommunicatorTest { String messageID2 = UUID.randomUUID().toString(); final ListenableFuture> resultFuture2 = sendRequest(messageID2, true); - communicator.onMessage(mockSession, createSuccessResponseMessage(messageID1)); - communicator.onMessage(mockSession, createSuccessResponseMessage(messageID2)); + communicator.onMessage(spySession, createSuccessResponseMessage(messageID1)); + communicator.onMessage(spySession, createSuccessResponseMessage(messageID2)); verifyResponseMessage(resultFuture1.get(), messageID1); verifyResponseMessage(resultFuture2.get(), messageID2); @@ -344,7 +347,7 @@ public class NetconfDeviceCommunicatorTest { String messageID = UUID.randomUUID().toString(); ListenableFuture> resultFuture = sendRequest(messageID, true); - communicator.onMessage(mockSession, createErrorResponseMessage(messageID)); + communicator.onMessage(spySession, createErrorResponseMessage(messageID)); RpcError rpcError = verifyErrorRpcResult(resultFuture.get(), ErrorType.RPC, ErrorTag.MISSING_ATTRIBUTE); assertEquals("RpcError message", "Missing attribute", rpcError.getMessage()); @@ -362,7 +365,7 @@ public class NetconfDeviceCommunicatorTest { String messageID = UUID.randomUUID().toString(); ListenableFuture> resultFuture = sendRequest(messageID, true); - communicator.onMessage(mockSession, createMultiErrorResponseMessage(messageID)); + communicator.onMessage(spySession, createMultiErrorResponseMessage(messageID)); RpcError rpcError = verifyErrorRpcResult(resultFuture.get(), ErrorType.PROTOCOL, ErrorTag.OPERATION_FAILED); @@ -438,7 +441,7 @@ public class NetconfDeviceCommunicatorTest { String messageID = UUID.randomUUID().toString(); ListenableFuture> resultFuture = sendRequest(messageID, true); - communicator.onMessage(mockSession, createSuccessResponseMessage(UUID.randomUUID().toString())); + communicator.onMessage(spySession, createSuccessResponseMessage(UUID.randomUUID().toString())); RpcError rpcError = verifyErrorRpcResult(resultFuture.get(), ErrorType.PROTOCOL, ErrorTag.BAD_ATTRIBUTE); assertFalse("RpcError message non-empty", Strings.isNullOrEmpty(rpcError.getMessage())); @@ -464,7 +467,7 @@ public class NetconfDeviceCommunicatorTest { ListenableFuture> resultFuture = sendRequest(notWorkingMessageID, false); assertEquals("ListenableFuture is null", false, resultFuture instanceof UncancellableFuture); - communicator.onMessage(mockSession, createSuccessResponseMessage(messageID.get(0))); + communicator.onMessage(spySession, createSuccessResponseMessage(messageID.get(0))); resultFuture = sendRequest(messageID.get(0), false); assertNotNull("ListenableFuture is null", resultFuture); -- 2.36.6