2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.netconf.topology.impl;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.ArgumentMatchers.any;
16 import static org.mockito.Mockito.doNothing;
17 import static org.mockito.Mockito.doReturn;
18 import static org.mockito.Mockito.mock;
19 import static org.mockito.Mockito.spy;
20 import static org.mockito.Mockito.times;
21 import static org.mockito.Mockito.verify;
22 import static org.mockito.Mockito.when;
23 import static org.opendaylight.mdsal.common.api.CommitInfo.emptyFluentFuture;
25 import com.google.common.util.concurrent.Futures;
26 import com.google.common.util.concurrent.ListenableFuture;
27 import com.google.common.util.concurrent.MoreExecutors;
28 import io.netty.util.concurrent.EventExecutor;
29 import java.util.Collection;
30 import java.util.HashSet;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.mockito.Mock;
35 import org.mockito.junit.MockitoJUnitRunner;
36 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
37 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
38 import org.opendaylight.controller.config.threadpool.ThreadPool;
39 import org.opendaylight.mdsal.binding.api.DataBroker;
40 import org.opendaylight.mdsal.binding.api.DataObjectModification;
41 import org.opendaylight.mdsal.binding.api.DataTreeModification;
42 import org.opendaylight.mdsal.binding.api.WriteTransaction;
43 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
44 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
45 import org.opendaylight.netconf.client.NetconfClientDispatcher;
46 import org.opendaylight.netconf.client.NetconfClientSessionListener;
47 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
48 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
49 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
50 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
51 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
71 import org.opendaylight.yangtools.yang.binding.DataObject;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
75 import org.opendaylight.yangtools.yang.common.Uint16;
76 import org.opendaylight.yangtools.yang.common.Uint32;
78 @RunWith(MockitoJUnitRunner.StrictStubs.class)
79 public class NetconfTopologyImplTest {
81 private static final NodeId NODE_ID = new NodeId("testing-node");
82 private static final String TOPOLOGY_ID = "testing-topology";
85 private NetconfClientDispatcher mockedClientDispatcher;
88 private EventExecutor mockedEventExecutor;
91 private ScheduledThreadPool mockedKeepaliveExecutor;
94 private ThreadPool mockedProcessingExecutor;
97 private SchemaResourceManager mockedResourceManager;
100 private DataBroker dataBroker;
103 private DOMMountPointService mountPointService;
106 private AAAEncryptionService encryptionService;
108 private TestingNetconfTopologyImpl topology;
109 private TestingNetconfTopologyImpl spyTopology;
112 public void setUp() {
113 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
115 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
116 mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
119 spyTopology = spy(topology);
123 public void testInit() {
124 final WriteTransaction wtx = mock(WriteTransaction.class);
125 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
126 doNothing().when(wtx)
127 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
128 doReturn(emptyFluentFuture()).when(wtx).commit();
131 //verify initialization of topology
132 final InstanceIdentifier<NetworkTopology> networkTopologyId =
133 InstanceIdentifier.builder(NetworkTopology.class).build();
134 final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
135 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
136 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION, networkTopologyId, networkTopology);
137 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId, networkTopology);
138 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
139 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
140 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
141 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
145 public void testOnDataTreeChange() {
147 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
148 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
150 PathArgument pa = IdentifiableItem.of(Node.class, new NodeKey(NODE_ID));
151 when(newNode.getIdentifier()).thenReturn(pa);
153 final NodeBuilder nn = new NodeBuilder()
154 .addAugmentation(new NetconfNodeBuilder()
155 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
156 .setPort(new PortNumber(Uint16.valueOf(9999)))
157 .setReconnectOnChangedSchema(true)
158 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
159 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
160 .setKeepaliveDelay(Uint32.valueOf(1000))
162 .setCredentials(new LoginPasswordBuilder()
163 .setUsername("testuser")
164 .setPassword("testpassword")
168 when(newNode.getDataAfter()).thenReturn(nn.build());
171 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
172 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
173 when(ch.getRootNode()).thenReturn(newNode);
175 spyTopology.onDataTreeChanged(changes);
176 verify(spyTopology).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
178 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
179 spyTopology.onDataTreeChanged(changes);
180 verify(spyTopology).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
182 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
183 spyTopology.onDataTreeChanged(changes);
185 //one in previous creating and deleting node and one in updating
186 verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
187 verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
193 public void testGetClientConfig() {
194 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
196 final NetconfNode testingNode = new NetconfNodeBuilder()
197 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
198 .setPort(new PortNumber(Uint16.valueOf(9999)))
199 .setReconnectOnChangedSchema(true)
200 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
201 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
202 .setKeepaliveDelay(Uint32.valueOf(1000))
204 .setCredentials(new LoginPasswordBuilder()
205 .setUsername("testuser").setPassword("testpassword").build())
207 final NetconfReconnectingClientConfiguration configuration =
208 spyTopology.getClientConfig(sessionListener, testingNode);
209 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
210 assertNotNull(configuration.getAuthHandler());
211 assertNull(configuration.getSslHandlerFactory());
214 final NetconfNode testingNode2 = new NetconfNodeBuilder()
215 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
216 .setPort(new PortNumber(Uint16.valueOf(9999)))
217 .setReconnectOnChangedSchema(true)
218 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
219 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
220 .setKeepaliveDelay(Uint32.valueOf(1000))
222 .setCredentials(new LoginPasswordBuilder()
223 .setUsername("testuser").setPassword("testpassword").build())
225 final NetconfReconnectingClientConfiguration configuration2 =
226 spyTopology.getClientConfig(sessionListener, testingNode2);
227 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
228 assertNotNull(configuration2.getAuthHandler());
229 assertNull(configuration2.getSslHandlerFactory());
232 final NetconfNode testingNode3 = new NetconfNodeBuilder()
233 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
234 .setPort(new PortNumber(Uint16.valueOf(9999)))
235 .setReconnectOnChangedSchema(true)
236 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
237 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
238 .setKeepaliveDelay(Uint32.valueOf(1000))
240 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build())
241 .setCredentials(new LoginPasswordBuilder()
242 .setUsername("testuser").setPassword("testpassword").build())
244 final NetconfReconnectingClientConfiguration configuration3 =
245 spyTopology.getClientConfig(sessionListener, testingNode3);
246 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
247 assertNotNull(configuration3.getAuthHandler());
248 assertNull(configuration3.getSslHandlerFactory());
251 final NetconfNode testingNode4 = new NetconfNodeBuilder()
252 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
253 .setPort(new PortNumber(Uint16.valueOf(9999)))
254 .setReconnectOnChangedSchema(true)
255 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
256 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
257 .setKeepaliveDelay(Uint32.valueOf(1000))
259 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
260 .setCredentials(new LoginPasswordBuilder()
261 .setUsername("testuser").setPassword("testpassword").build())
263 final NetconfReconnectingClientConfiguration configuration4 =
264 spyTopology.getClientConfig(sessionListener, testingNode4);
265 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
266 assertNull(configuration4.getAuthHandler());
267 assertNotNull(configuration4.getSslHandlerFactory());
270 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
272 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
273 final EventExecutor eventExecutor,
274 final ScheduledThreadPool keepaliveExecutor,
275 final ThreadPool processingExecutor,
276 final SchemaResourceManager schemaRepositoryProvider,
277 final DataBroker dataBroker, final DOMMountPointService mountPointService,
278 final AAAEncryptionService encryptionService) {
279 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
280 processingExecutor, schemaRepositoryProvider, dataBroker,
281 mountPointService, encryptionService);
285 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
286 return Futures.immediateFuture(new NetconfDeviceCapabilities());
290 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
291 return Futures.immediateFuture(null);
296 public void hideCredentialsTest() {
297 final String userName = "admin";
298 final String password = "pa$$word";
299 final Node node = new NodeBuilder()
300 .addAugmentation(new NetconfNodeBuilder()
301 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
302 .setPort(new PortNumber(Uint16.valueOf(9999)))
303 .setReconnectOnChangedSchema(true)
304 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
305 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
306 .setKeepaliveDelay(Uint32.valueOf(1000))
308 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
309 .setCredentials(new LoginPasswordBuilder()
310 .setUsername(userName)
311 .setPassword(password)
314 .setNodeId(NodeId.getDefaultInstance("junos"))
316 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
317 assertTrue(transformedNetconfNode.contains("credentials=***"));
318 assertFalse(transformedNetconfNode.contains(userName));
319 assertFalse(transformedNetconfNode.contains(password));