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.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
52 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.DefaultBaseNetconfSchemas;
53 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol.Name;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.ProtocolBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.LoginPasswordBuilder;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopologyBuilder;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
72 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
73 import org.opendaylight.yangtools.yang.binding.DataObject;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
76 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
77 import org.opendaylight.yangtools.yang.common.Uint16;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.opendaylight.yangtools.yang.parser.impl.YangParserFactoryImpl;
81 @RunWith(MockitoJUnitRunner.StrictStubs.class)
82 public class NetconfTopologyImplTest {
84 private static final NodeId NODE_ID = new NodeId("testing-node");
85 private static final String TOPOLOGY_ID = "testing-topology";
88 private NetconfClientDispatcher mockedClientDispatcher;
91 private EventExecutor mockedEventExecutor;
94 private ScheduledThreadPool mockedKeepaliveExecutor;
97 private ThreadPool mockedProcessingExecutor;
100 private SchemaResourceManager mockedResourceManager;
103 private DataBroker dataBroker;
106 private DOMMountPointService mountPointService;
109 private AAAEncryptionService encryptionService;
111 private TestingNetconfTopologyImpl topology;
112 private TestingNetconfTopologyImpl spyTopology;
115 public void setUp() {
116 when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
118 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
119 mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
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 PathArgument pa = IdentifiableItem.of(Node.class, new NodeKey(NODE_ID));
154 when(newNode.getIdentifier()).thenReturn(pa);
156 final NodeBuilder nn = new NodeBuilder()
157 .addAugmentation(new NetconfNodeBuilder()
158 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
159 .setPort(new PortNumber(Uint16.valueOf(9999)))
160 .setReconnectOnChangedSchema(true)
161 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
162 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
163 .setKeepaliveDelay(Uint32.valueOf(1000))
165 .setCredentials(new LoginPasswordBuilder()
166 .setUsername("testuser")
167 .setPassword("testpassword")
171 when(newNode.getDataAfter()).thenReturn(nn.build());
174 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
175 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
176 when(ch.getRootNode()).thenReturn(newNode);
178 spyTopology.onDataTreeChanged(changes);
179 verify(spyTopology).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
181 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
182 spyTopology.onDataTreeChanged(changes);
183 verify(spyTopology).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
185 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
186 spyTopology.onDataTreeChanged(changes);
188 //one in previous creating and deleting node and one in updating
189 verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
190 verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
196 public void testGetClientConfig() {
197 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
199 final NetconfNode testingNode = new NetconfNodeBuilder()
200 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
201 .setPort(new PortNumber(Uint16.valueOf(9999)))
202 .setReconnectOnChangedSchema(true)
203 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
204 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
205 .setKeepaliveDelay(Uint32.valueOf(1000))
207 .setCredentials(new LoginPasswordBuilder()
208 .setUsername("testuser").setPassword("testpassword").build())
210 final NetconfReconnectingClientConfiguration configuration =
211 spyTopology.getClientConfig(sessionListener, testingNode);
212 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
213 assertNotNull(configuration.getAuthHandler());
214 assertNull(configuration.getSslHandlerFactory());
217 final NetconfNode testingNode2 = new NetconfNodeBuilder()
218 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
219 .setPort(new PortNumber(Uint16.valueOf(9999)))
220 .setReconnectOnChangedSchema(true)
221 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
222 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
223 .setKeepaliveDelay(Uint32.valueOf(1000))
225 .setCredentials(new LoginPasswordBuilder()
226 .setUsername("testuser").setPassword("testpassword").build())
228 final NetconfReconnectingClientConfiguration configuration2 =
229 spyTopology.getClientConfig(sessionListener, testingNode2);
230 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
231 assertNotNull(configuration2.getAuthHandler());
232 assertNull(configuration2.getSslHandlerFactory());
235 final NetconfNode testingNode3 = new NetconfNodeBuilder()
236 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
237 .setPort(new PortNumber(Uint16.valueOf(9999)))
238 .setReconnectOnChangedSchema(true)
239 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
240 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
241 .setKeepaliveDelay(Uint32.valueOf(1000))
243 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build())
244 .setCredentials(new LoginPasswordBuilder()
245 .setUsername("testuser").setPassword("testpassword").build())
247 final NetconfReconnectingClientConfiguration configuration3 =
248 spyTopology.getClientConfig(sessionListener, testingNode3);
249 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
250 assertNotNull(configuration3.getAuthHandler());
251 assertNull(configuration3.getSslHandlerFactory());
254 final NetconfNode testingNode4 = new NetconfNodeBuilder()
255 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
256 .setPort(new PortNumber(Uint16.valueOf(9999)))
257 .setReconnectOnChangedSchema(true)
258 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
259 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
260 .setKeepaliveDelay(Uint32.valueOf(1000))
262 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
263 .setCredentials(new LoginPasswordBuilder()
264 .setUsername("testuser").setPassword("testpassword").build())
266 final NetconfReconnectingClientConfiguration configuration4 =
267 spyTopology.getClientConfig(sessionListener, testingNode4);
268 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
269 assertNull(configuration4.getAuthHandler());
270 assertNotNull(configuration4.getSslHandlerFactory());
273 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
274 private static final BaseNetconfSchemas BASE_SCHEMAS =
275 new DefaultBaseNetconfSchemas(new YangParserFactoryImpl());
277 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
278 final EventExecutor eventExecutor,
279 final ScheduledThreadPool keepaliveExecutor,
280 final ThreadPool processingExecutor,
281 final SchemaResourceManager schemaRepositoryProvider,
282 final DataBroker dataBroker, final DOMMountPointService mountPointService,
283 final AAAEncryptionService encryptionService) {
284 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
285 processingExecutor, schemaRepositoryProvider, dataBroker,
286 mountPointService, encryptionService, BASE_SCHEMAS);
290 public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
291 return Futures.immediateFuture(new NetconfDeviceCapabilities());
295 public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
296 return Futures.immediateFuture(null);
301 public void hideCredentialsTest() {
302 final String userName = "admin";
303 final String password = "pa$$word";
304 final Node node = new NodeBuilder()
305 .addAugmentation(new NetconfNodeBuilder()
306 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
307 .setPort(new PortNumber(Uint16.valueOf(9999)))
308 .setReconnectOnChangedSchema(true)
309 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
310 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
311 .setKeepaliveDelay(Uint32.valueOf(1000))
313 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
314 .setCredentials(new LoginPasswordBuilder()
315 .setUsername(userName)
316 .setPassword(password)
319 .setNodeId(NodeId.getDefaultInstance("junos"))
321 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
322 assertTrue(transformedNetconfNode.contains("credentials=***"));
323 assertFalse(transformedNetconfNode.contains(userName));
324 assertFalse(transformedNetconfNode.contains(password));