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.Mockito.doReturn;
16 import static org.mockito.Mockito.mock;
17 import static org.mockito.Mockito.spy;
18 import static org.mockito.Mockito.times;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import com.google.common.util.concurrent.MoreExecutors;
25 import io.netty.util.concurrent.EventExecutor;
26 import java.util.Collection;
27 import java.util.HashSet;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.junit.runner.RunWith;
31 import org.mockito.Mock;
32 import org.mockito.junit.MockitoJUnitRunner;
33 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
34 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
35 import org.opendaylight.controller.config.threadpool.ThreadPool;
36 import org.opendaylight.mdsal.binding.api.DataBroker;
37 import org.opendaylight.mdsal.binding.api.DataObjectModification;
38 import org.opendaylight.mdsal.binding.api.DataTreeModification;
39 import org.opendaylight.mdsal.binding.api.RpcProviderService;
40 import org.opendaylight.mdsal.binding.api.WriteTransaction;
41 import org.opendaylight.mdsal.common.api.CommitInfo;
42 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
43 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
44 import org.opendaylight.netconf.client.NetconfClientDispatcher;
45 import org.opendaylight.netconf.client.NetconfClientSessionListener;
46 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
47 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
48 import org.opendaylight.netconf.client.mdsal.api.BaseNetconfSchemas;
49 import org.opendaylight.netconf.client.mdsal.api.NetconfKeystoreAdapter;
50 import org.opendaylight.netconf.client.mdsal.api.SchemaResourceManager;
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.Empty;
75 import org.opendaylight.yangtools.yang.common.Uint16;
76 import org.opendaylight.yangtools.yang.common.Uint32;
77 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
78 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
80 @RunWith(MockitoJUnitRunner.StrictStubs.class)
81 public class NetconfTopologyImplTest {
82 private static final NodeId NODE_ID = new NodeId("testing-node");
83 private static final String TOPOLOGY_ID = "testing-topology";
86 private NetconfClientDispatcher mockedClientDispatcher;
88 private EventExecutor mockedEventExecutor;
90 private ScheduledThreadPool mockedKeepaliveExecutor;
92 private ThreadPool mockedProcessingExecutor;
94 private SchemaResourceManager mockedResourceManager;
96 private DataBroker dataBroker;
98 private DOMMountPointService mountPointService;
100 private AAAEncryptionService encryptionService;
102 private RpcProviderService rpcProviderService;
104 private NetconfKeystoreAdapter keystoreAdapter;
106 private WriteTransaction wtx;
108 private TestingNetconfTopologyImpl topology;
109 private TestingNetconfTopologyImpl spyTopology;
112 public void setUp() {
113 doReturn(MoreExecutors.newDirectExecutorService()).when(mockedProcessingExecutor).getExecutor();
114 doReturn(wtx).when(dataBroker).newWriteOnlyTransaction();
115 doReturn(CommitInfo.emptyFluentFuture()).when(wtx).commit();
117 topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
118 mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
119 encryptionService, rpcProviderService, keystoreAdapter);
120 //verify initialization of topology
121 verify(wtx).merge(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.builder(NetworkTopology.class)
122 .child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))).build(),
123 new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build());
125 spyTopology = spy(topology);
129 public void testOnDataTreeChange() {
130 final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
131 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
133 NodeKey key = new NodeKey(NODE_ID);
134 PathArgument pa = IdentifiableItem.of(Node.class, key);
135 when(newNode.getIdentifier()).thenReturn(pa);
137 final NodeBuilder nn = new NodeBuilder()
139 .addAugmentation(new NetconfNodeBuilder()
140 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
141 .setPort(new PortNumber(Uint16.valueOf(9999)))
142 .setReconnectOnChangedSchema(true)
143 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
144 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
145 .setKeepaliveDelay(Uint32.valueOf(1000))
147 .setCredentials(new LoginPasswordBuilder()
148 .setUsername("testuser")
149 .setPassword("testpassword")
153 when(newNode.getDataAfter()).thenReturn(nn.build());
155 final Collection<DataTreeModification<Node>> changes = new HashSet<>();
156 final DataTreeModification<Node> ch = mock(DataTreeModification.class);
157 when(ch.getRootNode()).thenReturn(newNode);
159 spyTopology.onDataTreeChanged(changes);
160 verify(spyTopology).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
162 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
163 spyTopology.onDataTreeChanged(changes);
164 verify(spyTopology).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
166 when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
167 spyTopology.onDataTreeChanged(changes);
169 //one in previous creating and deleting node and one in updating
170 verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
171 verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
175 public void testGetClientConfig() {
176 final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
177 final NetconfNodeBuilder nodeBuilder = new NetconfNodeBuilder()
178 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
179 .setPort(new PortNumber(Uint16.valueOf(9999)))
180 .setReconnectOnChangedSchema(true)
181 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
182 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
183 .setKeepaliveDelay(Uint32.valueOf(1000))
184 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
185 .setMaxConnectionAttempts(Uint32.ZERO)
186 .setSleepFactor(Decimal64.valueOf("1.5"))
187 .setConnectionTimeoutMillis(Uint32.valueOf(20000));
189 final NetconfReconnectingClientConfiguration configuration =
190 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(true).build(), NODE_ID);
191 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
192 assertNotNull(configuration.getAuthHandler());
193 assertNull(configuration.getSslHandlerFactory());
195 final NetconfReconnectingClientConfiguration configuration2 =
196 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(false).build(), NODE_ID);
197 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
198 assertNotNull(configuration2.getAuthHandler());
199 assertNull(configuration2.getSslHandlerFactory());
201 final NetconfReconnectingClientConfiguration configuration3 =
202 spyTopology.getClientConfig(sessionListener, nodeBuilder
203 .setProtocol(new ProtocolBuilder().setName(Name.SSH).build()).build(), NODE_ID);
204 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
205 assertNotNull(configuration3.getAuthHandler());
206 assertNull(configuration3.getSslHandlerFactory());
208 final NetconfReconnectingClientConfiguration configuration4 =
209 spyTopology.getClientConfig(sessionListener, nodeBuilder
210 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build()).build(), NODE_ID);
211 assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
212 assertNull(configuration4.getAuthHandler());
213 assertNotNull(configuration4.getSslHandlerFactory());
216 public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
217 private static final BaseNetconfSchemas BASE_SCHEMAS;
221 BASE_SCHEMAS = new DefaultBaseNetconfSchemas(new DefaultYangParserFactory());
222 } catch (YangParserException e) {
223 throw new ExceptionInInitializerError(e);
227 public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
228 final EventExecutor eventExecutor,
229 final ScheduledThreadPool keepaliveExecutor,
230 final ThreadPool processingExecutor,
231 final SchemaResourceManager schemaRepositoryProvider,
232 final DataBroker dataBroker, final DOMMountPointService mountPointService,
233 final AAAEncryptionService encryptionService,
234 final RpcProviderService rpcProviderService,
235 final NetconfKeystoreAdapter keystoreAdapter) {
236 super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
237 schemaRepositoryProvider, dataBroker, mountPointService, encryptionService, rpcProviderService,
238 BASE_SCHEMAS, keystoreAdapter, null);
242 public ListenableFuture<Empty> connectNode(final NodeId nodeId, final Node configNode) {
243 return Futures.immediateFuture(Empty.value());
247 public ListenableFuture<Empty> disconnectNode(final NodeId nodeId) {
248 return Futures.immediateFuture(Empty.value());
253 public void hideCredentialsTest() {
254 final String userName = "admin";
255 final String password = "pa$$word";
256 final Node node = new NodeBuilder()
257 .addAugmentation(new NetconfNodeBuilder()
258 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
259 .setPort(new PortNumber(Uint16.valueOf(9999)))
260 .setReconnectOnChangedSchema(true)
261 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
262 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
263 .setKeepaliveDelay(Uint32.valueOf(1000))
265 .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
266 .setCredentials(new LoginPasswordBuilder()
267 .setUsername(userName)
268 .setPassword(password)
271 .setNodeId(NodeId.getDefaultInstance("junos"))
273 final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
274 assertTrue(transformedNetconfNode.contains("credentials=***"));
275 assertFalse(transformedNetconfNode.contains(userName));
276 assertFalse(transformedNetconfNode.contains(password));