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.assertSame;
15 import static org.junit.Assert.assertTrue;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.mock;
18 import static org.mockito.Mockito.spy;
19 import static org.mockito.Mockito.times;
20 import static org.mockito.Mockito.verify;
22 import com.google.common.util.concurrent.MoreExecutors;
23 import io.netty.util.concurrent.EventExecutor;
24 import java.util.Collection;
25 import java.util.HashSet;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.Mock;
30 import org.mockito.junit.MockitoJUnitRunner;
31 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
32 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
33 import org.opendaylight.controller.config.threadpool.ThreadPool;
34 import org.opendaylight.mdsal.binding.api.DataBroker;
35 import org.opendaylight.mdsal.binding.api.DataObjectModification;
36 import org.opendaylight.mdsal.binding.api.DataTreeModification;
37 import org.opendaylight.mdsal.binding.api.RpcProviderService;
38 import org.opendaylight.mdsal.binding.api.WriteTransaction;
39 import org.opendaylight.mdsal.common.api.CommitInfo;
40 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
41 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
42 import org.opendaylight.netconf.client.NetconfClientDispatcher;
43 import org.opendaylight.netconf.client.NetconfClientSessionListener;
44 import org.opendaylight.netconf.client.SslHandlerFactory;
45 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
46 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
47 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
48 import org.opendaylight.netconf.client.mdsal.api.CredentialProvider;
49 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
50 import org.opendaylight.netconf.client.mdsal.api.SslHandlerFactoryProvider;
51 import org.opendaylight.netconf.client.mdsal.impl.DefaultBaseNetconfSchemas;
52 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.Protocol.Name;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.connection.parameters.ProtocolBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.device.rev230430.credentials.credentials.LoginPasswordBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev221225.NetconfNodeBuilder;
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.NodeId;
63 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
71 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
72 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
73 import org.opendaylight.yangtools.yang.common.Decimal64;
74 import org.opendaylight.yangtools.yang.common.Uint16;
75 import org.opendaylight.yangtools.yang.common.Uint32;
76 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
77 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
79 @RunWith(MockitoJUnitRunner.StrictStubs.class)
80 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;
87 private EventExecutor mockedEventExecutor;
89 private ScheduledThreadPool mockedKeepaliveExecutor;
91 private ThreadPool mockedProcessingExecutor;
93 private SchemaResourceManager mockedResourceManager;
95 private DataBroker dataBroker;
97 private DOMMountPointService mountPointService;
99 private AAAEncryptionService encryptionService;
101 private RpcProviderService rpcProviderService;
103 private CredentialProvider credentialProvider;
105 private SslHandlerFactoryProvider sslHandlerFactoryProvider;
107 private WriteTransaction wtx;
109 private TestingNetconfTopologyImpl topology;
110 private TestingNetconfTopologyImpl spyTopology;
113 public void setUp() {
114 doReturn(MoreExecutors.newDirectExecutorService()).when(mockedProcessingExecutor).getExecutor();
115 doReturn(wtx).when(dataBroker).newWriteOnlyTransaction();
116 doReturn(CommitInfo.emptyFluentFuture()).when(wtx).commit();
118 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
119 mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
120 encryptionService, rpcProviderService, credentialProvider, sslHandlerFactoryProvider);
121 //verify initialization of topology
122 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
123 .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))).build(),
124 new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build());
126 spyTopology = spy(topology);
130 public void testOnDataTreeChange() {
131 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
132 doReturn(DataObjectModification.ModificationType.WRITE).when(newNode).getModificationType();
134 NodeKey key = new NodeKey(NODE_ID);
135 PathArgument pa = IdentifiableItem.of(Node.class, key);
136 doReturn(pa).when(newNode).getIdentifier();
138 final NodeBuilder nn = new NodeBuilder()
140 .addAugmentation(new NetconfNodeBuilder()
141 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
142 .setPort(new PortNumber(Uint16.valueOf(9999)))
143 .setReconnectOnChangedSchema(true)
144 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
145 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
146 .setKeepaliveDelay(Uint32.valueOf(1000))
148 .setCredentials(new LoginPasswordBuilder()
149 .setUsername("testuser")
150 .setPassword("testpassword")
153 doReturn(nn.build()).when(newNode).getDataAfter();
155 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
156 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
157 doReturn(newNode).when(ch).getRootNode();
159 spyTopology.onDataTreeChanged(changes);
160 verify(spyTopology).ensureNode(nn.build());
162 doReturn(DataObjectModification.ModificationType.DELETE).when(newNode).getModificationType();
163 spyTopology.onDataTreeChanged(changes);
164 verify(spyTopology).deleteNode(NetconfTopologyImpl.getNodeId(pa));
166 doReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED).when(newNode).getModificationType();
167 spyTopology.onDataTreeChanged(changes);
169 // one in previous creating and deleting node and one in updating
170 verify(spyTopology, times(2)).ensureNode(nn.build());
174 public void testGetClientConfig() {
175 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
176 final NetconfNodeBuilder nodeBuilder = new NetconfNodeBuilder()
177 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
178 .setPort(new PortNumber(Uint16.valueOf(9999)))
179 .setReconnectOnChangedSchema(true)
180 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
181 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
182 .setKeepaliveDelay(Uint32.valueOf(1000))
183 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
184 .setMaxConnectionAttempts(Uint32.ZERO)
185 .setSleepFactor(Decimal64.valueOf("1.5"))
186 .setConnectionTimeoutMillis(Uint32.valueOf(20000));
188 final NetconfReconnectingClientConfiguration configuration =
189 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(true).build(), NODE_ID);
190 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
191 assertNotNull(configuration.getAuthHandler());
192 assertNull(configuration.getSslHandlerFactory());
194 final NetconfReconnectingClientConfiguration configuration2 =
195 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(false).build(), NODE_ID);
196 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
197 assertNotNull(configuration2.getAuthHandler());
198 assertNull(configuration2.getSslHandlerFactory());
200 final NetconfReconnectingClientConfiguration configuration3 =
201 spyTopology.getClientConfig(sessionListener, nodeBuilder
202 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build()).build(), NODE_ID);
203 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
204 assertNotNull(configuration3.getAuthHandler());
205 assertNull(configuration3.getSslHandlerFactory());
207 final var sslHandlerFactory = mock(SslHandlerFactory.class);
208 doReturn(sslHandlerFactory).when(sslHandlerFactoryProvider).getSslHandlerFactory(null);
210 final NetconfReconnectingClientConfiguration configuration4 =
211 spyTopology.getClientConfig(sessionListener, nodeBuilder
212 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build()).build(), NODE_ID);
213 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
214 assertNull(configuration4.getAuthHandler());
215 assertSame(sslHandlerFactory, configuration4.getSslHandlerFactory());
218 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
219 private static final BaseNetconfSchemas BASE_SCHEMAS;
223 BASE_SCHEMAS = new DefaultBaseNetconfSchemas(new DefaultYangParserFactory());
224 } catch (YangParserException e) {
225 throw new ExceptionInInitializerError(e);
229 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
230 final EventExecutor eventExecutor,
231 final ScheduledThreadPool keepaliveExecutor,
232 final ThreadPool processingExecutor,
233 final SchemaResourceManager schemaRepositoryProvider,
234 final DataBroker dataBroker, final DOMMountPointService mountPointService,
235 final AAAEncryptionService encryptionService,
236 final RpcProviderService rpcProviderService,
237 final CredentialProvider credentialProvider,
238 final SslHandlerFactoryProvider sslHandlerFactoryProvider) {
239 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
240 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
241 BASE_SCHEMAS, credentialProvider, sslHandlerFactoryProvider, null);
245 public void ensureNode(final Node configNode) {
250 public void deleteNode(final NodeId nodeId) {
256 public void hideCredentialsTest() {
257 final String userName = "admin";
258 final String password = "pa$$word";
259 final Node node = new NodeBuilder()
260 .addAugmentation(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(Uint32.valueOf(1000))
265 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
266 .setKeepaliveDelay(Uint32.valueOf(1000))
268 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
269 .setCredentials(new LoginPasswordBuilder()
270 .setUsername(userName)
271 .setPassword(password)
274 .setNodeId(NodeId.getDefaultInstance("junos"))
276 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
277 assertTrue(transformedNetconfNode.contains("credentials=***"));
278 assertFalse(transformedNetconfNode.contains(userName));
279 assertFalse(transformedNetconfNode.contains(password));