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.mockito.ArgumentMatchers.any;
11 import static org.mockito.Mockito.doNothing;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.spy;
15 import static org.mockito.Mockito.times;
16 import static org.mockito.Mockito.verify;
17 import static org.mockito.Mockito.when;
18 import static org.opendaylight.mdsal.common.api.CommitInfo.emptyFluentFuture;
20 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import com.google.common.util.concurrent.MoreExecutors;
23 import io.netty.util.concurrent.EventExecutor;
24 import io.netty.util.concurrent.Future;
25 import io.netty.util.concurrent.ImmediateEventExecutor;
26 import io.netty.util.concurrent.SucceededFuture;
27 import java.util.Collection;
28 import java.util.HashSet;
29 import org.junit.Assert;
30 import org.junit.Before;
31 import org.junit.Test;
32 import org.mockito.Mock;
33 import org.mockito.MockitoAnnotations;
34 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
35 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
36 import org.opendaylight.controller.config.threadpool.ThreadPool;
37 import org.opendaylight.mdsal.binding.api.DataBroker;
38 import org.opendaylight.mdsal.binding.api.DataObjectModification;
39 import org.opendaylight.mdsal.binding.api.DataTreeModification;
40 import org.opendaylight.mdsal.binding.api.WriteTransaction;
41 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
42 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
43 import org.opendaylight.netconf.client.NetconfClientDispatcher;
44 import org.opendaylight.netconf.client.NetconfClientSessionListener;
45 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
46 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
47 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
48 import org.opendaylight.netconf.topology.AbstractNetconfTopology;
49 import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
59 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
60 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
61 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
62 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
69 import org.opendaylight.yangtools.yang.binding.DataObject;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.opendaylight.yangtools.yang.common.Uint16;
72 import org.opendaylight.yangtools.yang.common.Uint32;
73 import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
75 public class NetconfTopologyImplTest {
77 private static final NodeId NODE_ID = new NodeId("testing-node");
78 private static final String TOPOLOGY_ID = "testing-topology";
81 private NetconfClientDispatcher mockedClientDispatcher;
84 private EventExecutor mockedEventExecutor;
87 private ScheduledThreadPool mockedKeepaliveExecutor;
90 private ThreadPool mockedProcessingExecutor;
93 private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
96 private DataBroker dataBroker;
99 private DOMMountPointService mountPointService;
102 private AAAEncryptionService encryptionService;
104 private TestingNetconfTopologyImpl topology;
105 private TestingNetconfTopologyImpl spyTopology;
108 public void setUp() {
109 MockitoAnnotations.initMocks(this);
111 when(mockedSchemaRepositoryProvider.getSharedSchemaRepository())
112 .thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
113 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
114 final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
115 when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class)))
118 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
119 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
120 dataBroker, mountPointService, encryptionService);
122 spyTopology = spy(topology);
126 public void testInit() {
127 final WriteTransaction wtx = mock(WriteTransaction.class);
128 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
129 doNothing().when(wtx)
130 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
131 doReturn(emptyFluentFuture()).when(wtx).commit();
134 //verify initialization of topology
135 final InstanceIdentifier<NetworkTopology> networkTopologyId =
136 InstanceIdentifier.builder(NetworkTopology.class).build();
137 final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
138 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
139 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION, networkTopologyId, networkTopology);
140 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId, networkTopology);
141 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
142 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
143 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
144 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
148 public void testOnDataTreeChange() {
150 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
151 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
153 InstanceIdentifier.PathArgument pa = null;
155 for (final InstanceIdentifier.PathArgument p
156 : TopologyUtil.createTopologyListPath(TOPOLOGY_ID)
157 .child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
161 when(newNode.getIdentifier()).thenReturn(pa);
164 final NetconfNode testingNode = new NetconfNodeBuilder()
165 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
166 .setPort(new PortNumber(Uint16.valueOf(9999)))
167 .setReconnectOnChangedSchema(true)
168 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
169 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
170 .setKeepaliveDelay(Uint32.valueOf(1000))
172 .setCredentials(new LoginPasswordBuilder()
173 .setUsername("testuser").setPassword("testpassword").build())
176 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
178 when(newNode.getDataAfter()).thenReturn(nn.build());
181 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
182 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
183 when(ch.getRootNode()).thenReturn(newNode);
185 spyTopology.onDataTreeChanged(changes);
186 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
188 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
189 spyTopology.onDataTreeChanged(changes);
190 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
192 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
193 spyTopology.onDataTreeChanged(changes);
195 //one in previous creating and deleting node and one in updating
196 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
197 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
203 public void testGetClientConfig() {
204 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
206 final NetconfNode testingNode = new NetconfNodeBuilder()
207 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
208 .setPort(new PortNumber(Uint16.valueOf(9999)))
209 .setReconnectOnChangedSchema(true)
210 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
211 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
212 .setKeepaliveDelay(Uint32.valueOf(1000))
214 .setCredentials(new LoginPasswordBuilder()
215 .setUsername("testuser").setPassword("testpassword").build())
217 final NetconfReconnectingClientConfiguration configuration =
218 spyTopology.getClientConfig(sessionListener, testingNode);
219 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
220 Assert.assertNotNull(configuration.getAuthHandler());
221 Assert.assertNull(configuration.getSslHandlerFactory());
224 final NetconfNode testingNode2 = new NetconfNodeBuilder()
225 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
226 .setPort(new PortNumber(Uint16.valueOf(9999)))
227 .setReconnectOnChangedSchema(true)
228 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
229 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
230 .setKeepaliveDelay(Uint32.valueOf(1000))
232 .setCredentials(new LoginPasswordBuilder()
233 .setUsername("testuser").setPassword("testpassword").build())
235 final NetconfReconnectingClientConfiguration configuration2 =
236 spyTopology.getClientConfig(sessionListener, testingNode2);
237 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
238 Assert.assertNotNull(configuration2.getAuthHandler());
239 Assert.assertNull(configuration2.getSslHandlerFactory());
242 final NetconfNode testingNode3 = new NetconfNodeBuilder()
243 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
244 .setPort(new PortNumber(Uint16.valueOf(9999)))
245 .setReconnectOnChangedSchema(true)
246 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
247 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
248 .setKeepaliveDelay(Uint32.valueOf(1000))
250 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build())
251 .setCredentials(new LoginPasswordBuilder()
252 .setUsername("testuser").setPassword("testpassword").build())
254 final NetconfReconnectingClientConfiguration configuration3 =
255 spyTopology.getClientConfig(sessionListener, testingNode3);
256 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
257 Assert.assertNotNull(configuration3.getAuthHandler());
258 Assert.assertNull(configuration3.getSslHandlerFactory());
261 final NetconfNode testingNode4 = new NetconfNodeBuilder()
262 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
263 .setPort(new PortNumber(Uint16.valueOf(9999)))
264 .setReconnectOnChangedSchema(true)
265 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
266 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
267 .setKeepaliveDelay(Uint32.valueOf(1000))
269 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
270 .setCredentials(new LoginPasswordBuilder()
271 .setUsername("testuser").setPassword("testpassword").build())
273 final NetconfReconnectingClientConfiguration configuration4 =
274 spyTopology.getClientConfig(sessionListener, testingNode4);
275 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
276 Assert.assertNull(configuration4.getAuthHandler());
277 Assert.assertNotNull(configuration4.getSslHandlerFactory());
280 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
282 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
283 final EventExecutor eventExecutor,
284 final ScheduledThreadPool keepaliveExecutor,
285 final ThreadPool processingExecutor,
286 final SchemaRepositoryProvider schemaRepositoryProvider,
287 final DataBroker dataBroker, final DOMMountPointService mountPointService,
288 final AAAEncryptionService encryptionService) {
289 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
290 processingExecutor, schemaRepositoryProvider, dataBroker,
291 mountPointService, encryptionService);
295 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
296 return Futures.immediateFuture(new NetconfDeviceCapabilities());
300 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
301 return Futures.immediateFuture(null);
306 public void hideCredentialsTest() {
307 final String userName = "admin";
308 final String password = "pa$$word";
309 final NetconfNode netconfNode = new NetconfNodeBuilder()
310 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
311 .setPort(new PortNumber(Uint16.valueOf(9999)))
312 .setReconnectOnChangedSchema(true)
313 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
314 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
315 .setKeepaliveDelay(Uint32.valueOf(1000))
317 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
318 .setCredentials(new LoginPasswordBuilder()
319 .setUsername(userName).setPassword(password).build())
321 final Node node = new NodeBuilder()
322 .addAugmentation(NetconfNode.class, netconfNode)
323 .setNodeId(NodeId.getDefaultInstance("junos"))
325 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
326 Assert.assertTrue(transformedNetconfNode.contains("credentials=***"));
327 Assert.assertFalse(transformedNetconfNode.contains(userName));
328 Assert.assertFalse(transformedNetconfNode.contains(password));