3e0e399a43a227d32ccf52509ae6fd93e0762176
[netconf.git] / netconf / netconf-topology-impl / src / test / java / org / opendaylight / netconf / topology / impl / NetconfTopologyImplTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.topology.impl;
9
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;
24
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.RpcProviderService;
43 import org.opendaylight.mdsal.binding.api.WriteTransaction;
44 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
45 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
46 import org.opendaylight.netconf.client.NetconfClientDispatcher;
47 import org.opendaylight.netconf.client.NetconfClientSessionListener;
48 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
49 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
50 import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
51 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
52 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.BaseNetconfSchemas;
53 import org.opendaylight.netconf.sal.connect.netconf.schema.mapping.DefaultBaseNetconfSchemas;
54 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
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.NodeId;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
66 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
67 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
68 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
69 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
70 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
71 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
72 import org.opendaylight.yangtools.yang.binding.DataObject;
73 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
74 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
75 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
76 import org.opendaylight.yangtools.yang.common.Decimal64;
77 import org.opendaylight.yangtools.yang.common.Uint16;
78 import org.opendaylight.yangtools.yang.common.Uint32;
79 import org.opendaylight.yangtools.yang.parser.api.YangParserException;
80 import org.opendaylight.yangtools.yang.parser.impl.DefaultYangParserFactory;
81
82 @RunWith(MockitoJUnitRunner.StrictStubs.class)
83 public class NetconfTopologyImplTest {
84
85     private static final NodeId NODE_ID = new NodeId("testing-node");
86     private static final String TOPOLOGY_ID = "testing-topology";
87
88     @Mock
89     private NetconfClientDispatcher mockedClientDispatcher;
90
91     @Mock
92     private EventExecutor mockedEventExecutor;
93
94     @Mock
95     private ScheduledThreadPool mockedKeepaliveExecutor;
96
97     @Mock
98     private ThreadPool mockedProcessingExecutor;
99
100     @Mock
101     private SchemaResourceManager mockedResourceManager;
102
103     @Mock
104     private DataBroker dataBroker;
105
106     @Mock
107     private DOMMountPointService mountPointService;
108
109     @Mock
110     private AAAEncryptionService encryptionService;
111
112     @Mock
113     private RpcProviderService rpcProviderService;
114
115     private TestingNetconfTopologyImpl topology;
116     private TestingNetconfTopologyImpl spyTopology;
117
118     @Before
119     public void setUp() {
120         when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
121
122         topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
123             mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
124             encryptionService, rpcProviderService);
125
126         spyTopology = spy(topology);
127     }
128
129     @Test
130     public void testInit() {
131         final WriteTransaction wtx = mock(WriteTransaction.class);
132         when(dataBroker.newWriteOnlyTransaction()).thenReturn(wtx);
133         doNothing().when(wtx)
134                 .merge(any(LogicalDatastoreType.class), any(InstanceIdentifier.class), any(DataObject.class));
135         doReturn(emptyFluentFuture()).when(wtx).commit();
136         topology.init();
137
138         //verify initialization of topology
139         final InstanceIdentifier<NetworkTopology> networkTopologyId =
140                 InstanceIdentifier.builder(NetworkTopology.class).build();
141         final Topology topo = new TopologyBuilder().setTopologyId(new TopologyId(TOPOLOGY_ID)).build();
142         verify(wtx).merge(LogicalDatastoreType.CONFIGURATION,
143                 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
144         verify(wtx).merge(LogicalDatastoreType.OPERATIONAL,
145                 networkTopologyId.child(Topology.class, new TopologyKey(new TopologyId(TOPOLOGY_ID))), topo);
146     }
147
148     @Test
149     public void testOnDataTreeChange() {
150         final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
151         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
152
153         NodeKey key = new NodeKey(NODE_ID);
154         PathArgument pa = IdentifiableItem.of(Node.class, key);
155         when(newNode.getIdentifier()).thenReturn(pa);
156
157         final NodeBuilder nn = new NodeBuilder()
158                 .withKey(key)
159                 .addAugmentation(new NetconfNodeBuilder()
160                     .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
161                     .setPort(new PortNumber(Uint16.valueOf(9999)))
162                     .setReconnectOnChangedSchema(true)
163                     .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
164                     .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
165                     .setKeepaliveDelay(Uint32.valueOf(1000))
166                     .setTcpOnly(true)
167                     .setCredentials(new LoginPasswordBuilder()
168                         .setUsername("testuser")
169                         .setPassword("testpassword")
170                         .build())
171                     .build());
172
173         when(newNode.getDataAfter()).thenReturn(nn.build());
174
175         final Collection<DataTreeModification<Node>> changes = new HashSet<>();
176         final DataTreeModification<Node> ch = mock(DataTreeModification.class);
177         when(ch.getRootNode()).thenReturn(newNode);
178         changes.add(ch);
179         spyTopology.onDataTreeChanged(changes);
180         verify(spyTopology).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
181
182         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.DELETE);
183         spyTopology.onDataTreeChanged(changes);
184         verify(spyTopology).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
185
186         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.SUBTREE_MODIFIED);
187         spyTopology.onDataTreeChanged(changes);
188
189         //one in previous creating and deleting node and one in updating
190         verify(spyTopology, times(2)).disconnectNode(NetconfTopologyImpl.getNodeId(pa));
191         verify(spyTopology, times(2)).connectNode(NetconfTopologyImpl.getNodeId(pa), nn.build());
192     }
193
194     @Test
195     public void testGetClientConfig() {
196         final NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
197         final NetconfNodeBuilder nodeBuilder = new NetconfNodeBuilder()
198                 .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
199                 .setPort(new PortNumber(Uint16.valueOf(9999)))
200                 .setReconnectOnChangedSchema(true)
201                 .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
202                 .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
203                 .setKeepaliveDelay(Uint32.valueOf(1000))
204                 .setCredentials(new LoginPasswordBuilder().setUsername("testuser").setPassword("testpassword").build())
205                 .setMaxConnectionAttempts(Uint32.ZERO)
206                 .setSleepFactor(Decimal64.valueOf("1.5"))
207                 .setConnectionTimeoutMillis(Uint32.valueOf(20000));
208
209         final NetconfReconnectingClientConfiguration configuration =
210                 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(true).build(), NODE_ID);
211         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TCP, configuration.getProtocol());
212         assertNotNull(configuration.getAuthHandler());
213         assertNull(configuration.getSslHandlerFactory());
214
215         final NetconfReconnectingClientConfiguration configuration2 =
216                 spyTopology.getClientConfig(sessionListener, nodeBuilder.setTcpOnly(false).build(), NODE_ID);
217         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration2.getProtocol());
218         assertNotNull(configuration2.getAuthHandler());
219         assertNull(configuration2.getSslHandlerFactory());
220
221         final NetconfReconnectingClientConfiguration configuration3 =
222                 spyTopology.getClientConfig(sessionListener, nodeBuilder
223                         .setProtocol(new ProtocolBuilder().setName(Name.SSH).build()).build(), NODE_ID);
224         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.SSH, configuration3.getProtocol());
225         assertNotNull(configuration3.getAuthHandler());
226         assertNull(configuration3.getSslHandlerFactory());
227
228         final NetconfReconnectingClientConfiguration configuration4 =
229                 spyTopology.getClientConfig(sessionListener, nodeBuilder
230                         .setProtocol(new ProtocolBuilder().setName(Name.TLS).build()).build(), NODE_ID);
231         assertEquals(NetconfClientConfiguration.NetconfClientProtocol.TLS, configuration4.getProtocol());
232         assertNull(configuration4.getAuthHandler());
233         assertNotNull(configuration4.getSslHandlerFactory());
234     }
235
236     public static class TestingNetconfTopologyImpl extends NetconfTopologyImpl {
237         private static final BaseNetconfSchemas BASE_SCHEMAS;
238
239         static {
240             try {
241                 BASE_SCHEMAS = new DefaultBaseNetconfSchemas(new DefaultYangParserFactory());
242             } catch (YangParserException e) {
243                 throw new ExceptionInInitializerError(e);
244             }
245         }
246
247         public TestingNetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
248                                           final EventExecutor eventExecutor,
249                                           final ScheduledThreadPool keepaliveExecutor,
250                                           final ThreadPool processingExecutor,
251                                           final SchemaResourceManager schemaRepositoryProvider,
252                                           final DataBroker dataBroker, final DOMMountPointService mountPointService,
253                                           final AAAEncryptionService encryptionService,
254                                           final RpcProviderService rpcProviderService) {
255             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
256                   processingExecutor, schemaRepositoryProvider, dataBroker,
257                   mountPointService, encryptionService, rpcProviderService, BASE_SCHEMAS);
258         }
259
260         @Override
261         public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
262             return Futures.immediateFuture(new NetconfDeviceCapabilities());
263         }
264
265         @Override
266         public ListenableFuture<Void> disconnectNode(final NodeId nodeId) {
267             return Futures.immediateFuture(null);
268         }
269     }
270
271     @Test
272     public void hideCredentialsTest() {
273         final String userName = "admin";
274         final String password = "pa$$word";
275         final Node node = new NodeBuilder()
276                 .addAugmentation(new NetconfNodeBuilder()
277                     .setHost(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))))
278                     .setPort(new PortNumber(Uint16.valueOf(9999)))
279                     .setReconnectOnChangedSchema(true)
280                     .setDefaultRequestTimeoutMillis(Uint32.valueOf(1000))
281                     .setBetweenAttemptsTimeoutMillis(Uint16.valueOf(100))
282                     .setKeepaliveDelay(Uint32.valueOf(1000))
283                     .setTcpOnly(false)
284                     .setProtocol(new ProtocolBuilder().setName(Name.TLS).build())
285                     .setCredentials(new LoginPasswordBuilder()
286                         .setUsername(userName)
287                         .setPassword(password)
288                         .build())
289                     .build())
290                 .setNodeId(NodeId.getDefaultInstance("junos"))
291                 .build();
292         final String transformedNetconfNode = AbstractNetconfTopology.hideCredentials(node);
293         assertTrue(transformedNetconfNode.contains("credentials=***"));
294         assertFalse(transformedNetconfNode.contains(userName));
295         assertFalse(transformedNetconfNode.contains(password));
296     }
297 }