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.parser.repo.SharedSchemaRepository;
74 public class NetconfTopologyImplTest {
76 private static final NodeId NODE_ID = new NodeId("testing-node");
77 private static final String TOPOLOGY_ID = "testing-topology";
80 private NetconfClientDispatcher mockedClientDispatcher;
83 private EventExecutor mockedEventExecutor;
86 private ScheduledThreadPool mockedKeepaliveExecutor;
89 private ThreadPool mockedProcessingExecutor;
92 private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
95 private DataBroker dataBroker;
98 private DOMMountPointService mountPointService;
101 private AAAEncryptionService encryptionService;
103 private TestingNetconfTopologyImpl topology;
104 private TestingNetconfTopologyImpl spyTopology;
107 public void setUp() {
108 MockitoAnnotations.initMocks(this);
110 when(mockedSchemaRepositoryProvider.getSharedSchemaRepository())
111 .thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
112 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
113 final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
114 when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class)))
117 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
118 mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
119 dataBroker, mountPointService, encryptionService);
121 spyTopology = spy(topology);
125 public void testInit() {
126 final WriteTransaction wtx = mock(WriteTransaction.class);
127 when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
128 doNothing().when(wtx)
129 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
130 doReturn(emptyFluentFuture()).when(wtx).commit();
133 //verify initialization of topology
134 final InstanceIdentifier<NetworkTopology> networkTopologyId =
135 InstanceIdentifier.builder(NetworkTopology.class).build();
136 final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
137 final NetworkTopology networkTopology = new NetworkTopologyBuilder().build();
138 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION, networkTopologyId, networkTopology);
139 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, networkTopologyId, networkTopology);
140 verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
141 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
142 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
143 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
147 public void testOnDataTreeChange() {
149 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
150 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
152 InstanceIdentifier.PathArgument pa = null;
154 for (final InstanceIdentifier.PathArgument p
155 : TopologyUtil.createTopologyListPath(TOPOLOGY_ID)
156 .child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
160 when(newNode.getIdentifier()).thenReturn(pa);
163 final NetconfNode testingNode = new NetconfNodeBuilder()
164 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
165 .setPort(new PortNumber(Uint16.valueOf(9999)))
166 .setReconnectOnChangedSchema(true)
167 .setDefaultRequestTimeoutMillis(1000L)
168 .setBetweenAttemptsTimeoutMillis(100)
169 .setKeepaliveDelay(1000L)
171 .setCredentials(new LoginPasswordBuilder()
172 .setUsername("testuser").setPassword("testpassword").build())
175 final NodeBuilder nn = new NodeBuilder().addAugmentation(NetconfNode.class, testingNode);
177 when(newNode.getDataAfter()).thenReturn(nn.build());
180 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
181 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
182 when(ch.getRootNode()).thenReturn(newNode);
184 spyTopology.onDataTreeChanged(changes);
185 verify(spyTopology).connectNode(TopologyUtil.getNodeId(pa), nn.build());
187 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
188 spyTopology.onDataTreeChanged(changes);
189 verify(spyTopology).disconnectNode(TopologyUtil.getNodeId(pa));
191 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
192 spyTopology.onDataTreeChanged(changes);
194 //one in previous creating and deleting node and one in updating
195 verify(spyTopology, times(2)).disconnectNode(TopologyUtil.getNodeId(pa));
196 verify(spyTopology, times(2)).connectNode(TopologyUtil.getNodeId(pa), nn.build());
202 public void testGetClientConfig() {
203 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
205 final NetconfNode testingNode = new NetconfNodeBuilder()
206 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
207 .setPort(new PortNumber(Uint16.valueOf(9999)))
208 .setReconnectOnChangedSchema(true)
209 .setDefaultRequestTimeoutMillis(1000L)
210 .setBetweenAttemptsTimeoutMillis(100)
211 .setKeepaliveDelay(1000L)
213 .setCredentials(new LoginPasswordBuilder()
214 .setUsername("testuser").setPassword("testpassword").build())
216 final NetconfReconnectingClientConfiguration configuration =
217 spyTopology.getClientConfig(sessionListener, testingNode);
218 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
219 Assert.assertNotNull(configuration.getAuthHandler());
220 Assert.assertNull(configuration.getSslHandlerFactory());
223 final NetconfNode testingNode2 = new NetconfNodeBuilder()
224 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
225 .setPort(new PortNumber(Uint16.valueOf(9999)))
226 .setReconnectOnChangedSchema(true)
227 .setDefaultRequestTimeoutMillis(1000L)
228 .setBetweenAttemptsTimeoutMillis(100)
229 .setKeepaliveDelay(1000L)
231 .setCredentials(new LoginPasswordBuilder()
232 .setUsername("testuser").setPassword("testpassword").build())
234 final NetconfReconnectingClientConfiguration configuration2 =
235 spyTopology.getClientConfig(sessionListener, testingNode2);
236 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
237 Assert.assertNotNull(configuration2.getAuthHandler());
238 Assert.assertNull(configuration2.getSslHandlerFactory());
241 final NetconfNode testingNode3 = new NetconfNodeBuilder()
242 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
243 .setPort(new PortNumber(Uint16.valueOf(9999)))
244 .setReconnectOnChangedSchema(true)
245 .setDefaultRequestTimeoutMillis(1000L)
246 .setBetweenAttemptsTimeoutMillis(100)
247 .setKeepaliveDelay(1000L)
249 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build())
250 .setCredentials(new LoginPasswordBuilder()
251 .setUsername("testuser").setPassword("testpassword").build())
253 final NetconfReconnectingClientConfiguration configuration3 =
254 spyTopology.getClientConfig(sessionListener, testingNode3);
255 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
256 Assert.assertNotNull(configuration3.getAuthHandler());
257 Assert.assertNull(configuration3.getSslHandlerFactory());
260 final NetconfNode testingNode4 = new NetconfNodeBuilder()
261 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
262 .setPort(new PortNumber(Uint16.valueOf(9999)))
263 .setReconnectOnChangedSchema(true)
264 .setDefaultRequestTimeoutMillis(1000L)
265 .setBetweenAttemptsTimeoutMillis(100)
266 .setKeepaliveDelay(1000L)
268 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
269 .setCredentials(new LoginPasswordBuilder()
270 .setUsername("testuser").setPassword("testpassword").build())
272 final NetconfReconnectingClientConfiguration configuration4 =
273 spyTopology.getClientConfig(sessionListener, testingNode4);
274 Assert.assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
275 Assert.assertNull(configuration4.getAuthHandler());
276 Assert.assertNotNull(configuration4.getSslHandlerFactory());
279 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
281 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
282 final EventExecutor eventExecutor,
283 final ScheduledThreadPool keepaliveExecutor,
284 final ThreadPool processingExecutor,
285 final SchemaRepositoryProvider schemaRepositoryProvider,
286 final DataBroker dataBroker, final DOMMountPointService mountPointService,
287 final AAAEncryptionService encryptionService) {
288 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
289 processingExecutor, schemaRepositoryProvider, dataBroker,
290 mountPointService, encryptionService);
294 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
295 return Futures.immediateFuture(new NetconfDeviceCapabilities());
299 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
300 return Futures.immediateFuture(null);
305 public void hideCredentialsTest() {
306 final String userName = "admin";
307 final String password = "pa$$word";
308 final NetconfNode netconfNode = new NetconfNodeBuilder()
309 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
310 .setPort(new PortNumber(Uint16.valueOf(9999)))
311 .setReconnectOnChangedSchema(true)
312 .setDefaultRequestTimeoutMillis(1000L)
313 .setBetweenAttemptsTimeoutMillis(100)
314 .setKeepaliveDelay(1000L)
316 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
317 .setCredentials(new LoginPasswordBuilder()
318 .setUsername(userName).setPassword(password).build())
320 final Node node = new NodeBuilder()
321 .addAugmentation(NetconfNode.class, netconfNode)
322 .setNodeId(NodeId.getDefaultInstance("junos"))
324 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
325 Assert.assertTrue(transformedNetconfNode.contains("credentials=***"));
326 Assert.assertFalse(transformedNetconfNode.contains(userName));
327 Assert.assertFalse(transformedNetconfNode.contains(password));