blob: 51bf91cc3920944f60d860ad2967dccbbcde46fd [file] [log] [blame]
Sean Condond2c8d472017-02-17 17:09:39 +00001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Sean Condond2c8d472017-02-17 17:09:39 +00003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Yuta HIGUCHIe3ae8212017-04-20 10:18:41 -070016package org.onosproject.netconf.ctl.impl;
Sean Condond2c8d472017-02-17 17:09:39 +000017
Aaron Kruglikov72db6422017-02-13 12:16:51 -080018import static org.hamcrest.Matchers.containsInAnyOrder;
Sean Condon54d82432017-07-26 22:27:25 +010019import static org.junit.Assert.assertEquals;
Sean Condond2c8d472017-02-17 17:09:39 +000020import static org.junit.Assert.assertNotNull;
Aaron Kruglikov72db6422017-02-13 12:16:51 -080021import static org.junit.Assert.assertThat;
Sean Condond2c8d472017-02-17 17:09:39 +000022import static org.junit.Assert.assertTrue;
23import static org.junit.Assert.fail;
Shivani Vaidya48df84e2017-04-13 13:48:17 -070024import static org.junit.Assert.assertFalse;
Yuta HIGUCHI89111d92017-05-04 11:29:17 -070025import static org.onosproject.netconf.DatastoreId.CANDIDATE;
26import static org.onosproject.netconf.DatastoreId.RUNNING;
Sean Condond2c8d472017-02-17 17:09:39 +000027
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070028import java.io.File;
Sean Condond2c8d472017-02-17 17:09:39 +000029import java.util.Arrays;
Aaron Kruglikov72db6422017-02-13 12:16:51 -080030import java.util.Collection;
Sean Condond2c8d472017-02-17 17:09:39 +000031import java.util.Optional;
Sean Condon54d82432017-07-26 22:27:25 +010032import java.util.OptionalInt;
Sean Condond2c8d472017-02-17 17:09:39 +000033import java.util.concurrent.Callable;
34import java.util.concurrent.ExecutorService;
35import java.util.concurrent.Executors;
36import java.util.concurrent.FutureTask;
37import java.util.regex.Pattern;
38
Kamil Stasiak9f59f442017-05-02 11:02:24 +020039import com.google.common.collect.ImmutableList;
Sean Condond2c8d472017-02-17 17:09:39 +000040import org.apache.sshd.common.NamedFactory;
41import org.apache.sshd.server.Command;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070042import org.apache.sshd.server.SshServer;
43import org.apache.sshd.server.auth.password.PasswordAuthenticator;
Sean Condond2c8d472017-02-17 17:09:39 +000044import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
45import org.apache.sshd.server.session.ServerSession;
46import org.junit.AfterClass;
47import org.junit.BeforeClass;
48import org.junit.Test;
49import org.onlab.junit.TestTools;
50import org.onlab.packet.Ip4Address;
Sean Condon54d82432017-07-26 22:27:25 +010051import org.onosproject.netconf.DatastoreId;
52import org.onosproject.netconf.NetconfController;
Sean Condond2c8d472017-02-17 17:09:39 +000053import org.onosproject.netconf.NetconfDeviceInfo;
54import org.onosproject.netconf.NetconfException;
55import org.onosproject.netconf.NetconfSession;
56import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
Aaron Kruglikov72db6422017-02-13 12:16:51 -080059
Sean Condond2c8d472017-02-17 17:09:39 +000060/**
61 * Unit tests for NetconfSession.
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070062 * <p>
Sean Condond2c8d472017-02-17 17:09:39 +000063 * Sets up an SSH Server with Apache SSHD and connects to it using 2 clients
64 * Truly verifies that the NETCONF flows are compliant with a NETCONF server.
65 */
66public class NetconfSessionImplTest {
67 private static final Logger log = LoggerFactory
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070068 .getLogger(NetconfSessionImplTest.class);
Sean Condond2c8d472017-02-17 17:09:39 +000069
Sean Condond2c8d472017-02-17 17:09:39 +000070 private static final String TEST_USERNAME = "netconf";
71 private static final String TEST_PASSWORD = "netconf123";
72 private static final String TEST_HOSTNAME = "127.0.0.1";
Shivani Vaidya48df84e2017-04-13 13:48:17 -070073
Sean Condond2c8d472017-02-17 17:09:39 +000074 private static final String TEST_SERFILE =
75 System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + "testkey.ser";
76
77 private static final String SAMPLE_REQUEST =
78 "<some-yang-element xmlns=\"some-namespace\">"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070079 + "<some-child-element/>"
80 + "</some-yang-element>";
Sean Condond2c8d472017-02-17 17:09:39 +000081
Shivani Vaidya48df84e2017-04-13 13:48:17 -070082 private static final String EDIT_CONFIG_REQUEST =
83 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc message-id=\"6\" "
84 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
85 + "<edit-config>\n"
86 + "<target><running/></target>\n"
87 + "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
88 + "<some-yang-element xmlns=\"some-namespace\">"
89 + "<some-child-element/></some-yang-element></config>\n"
90 + "</edit-config>\n"
91 + "</rpc>]]>]]>";
92
Sean Condond2c8d472017-02-17 17:09:39 +000093 private static NetconfSession session1;
94 private static NetconfSession session2;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020095 private static NetconfSession session3;
96 private static NetconfSession session4;
Sean Condond2c8d472017-02-17 17:09:39 +000097 private static SshServer sshServerNetconf;
98
99 @BeforeClass
100 public static void setUp() throws Exception {
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700101 int portNumber = TestTools.findAvailablePort(50830);
Sean Condond2c8d472017-02-17 17:09:39 +0000102 sshServerNetconf = SshServer.setUpDefaultServer();
Sean Condond2c8d472017-02-17 17:09:39 +0000103 sshServerNetconf.setPasswordAuthenticator(
104 new PasswordAuthenticator() {
105 @Override
106 public boolean authenticate(
107 String username,
108 String password,
109 ServerSession session) {
110 return TEST_USERNAME.equals(username) && TEST_PASSWORD.equals(password);
111 }
112 });
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700113 sshServerNetconf.setPort(portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700114 SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
115 provider.setFile(new File(TEST_SERFILE));
116 sshServerNetconf.setKeyPairProvider(provider);
Sean Condond2c8d472017-02-17 17:09:39 +0000117 sshServerNetconf.setSubsystemFactories(
118 Arrays.<NamedFactory<Command>>asList(new NetconfSshdTestSubsystem.Factory()));
119 sshServerNetconf.open();
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700120 log.info("SSH Server opened on port {}", portNumber);
Sean Condond2c8d472017-02-17 17:09:39 +0000121
Sean Condon54d82432017-07-26 22:27:25 +0100122 NetconfController netconfCtl = new NetconfControllerImpl();
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700123 NetconfControllerImpl.netconfConnectTimeout = NetconfControllerImpl.DEFAULT_CONNECT_TIMEOUT_SECONDS;
124 NetconfControllerImpl.netconfIdleTimeout = NetconfControllerImpl.DEFAULT_IDLE_TIMEOUT_SECONDS;
125 NetconfControllerImpl.netconfReplyTimeout = NetconfControllerImpl.DEFAULT_REPLY_TIMEOUT_SECONDS;
Sean Condon54d82432017-07-26 22:27:25 +0100126
127 NetconfDeviceInfo deviceInfo1 = new NetconfDeviceInfo(
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700128 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), portNumber);
Sean Condond2c8d472017-02-17 17:09:39 +0000129
Sean Condon54d82432017-07-26 22:27:25 +0100130 session1 = new NetconfSessionImpl(deviceInfo1, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Sean Condond2c8d472017-02-17 17:09:39 +0000131 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session1.getSessionId());
132 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("-1"));
133 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("0"));
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200134 assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(
135 NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES.toArray()));
Sean Condon54d82432017-07-26 22:27:25 +0100136
137 NetconfDeviceInfo deviceInfo2 = new NetconfDeviceInfo(
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700138 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), portNumber);
Sean Condon54d82432017-07-26 22:27:25 +0100139 deviceInfo2.setConnectTimeoutSec(OptionalInt.of(11));
140 deviceInfo2.setReplyTimeoutSec(OptionalInt.of(10));
141 deviceInfo2.setIdleTimeoutSec(OptionalInt.of(12));
142 session2 = new NetconfSessionMinaImpl(deviceInfo2, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Sean Condond2c8d472017-02-17 17:09:39 +0000143 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session2.getSessionId());
144 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("-1"));
145 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("0"));
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200146 assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(
147 NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES.toArray()));
Sean Condon54d82432017-07-26 22:27:25 +0100148 session3 = new NetconfSessionImpl(deviceInfo1);
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200149 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session3.getSessionId());
150 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("-1"));
151 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("0"));
152 assertThat(session3.getDeviceCapabilitiesSet(), containsInAnyOrder(
153 NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1.toArray()));
Sean Condon54d82432017-07-26 22:27:25 +0100154 session4 = new NetconfSessionImpl(deviceInfo1);
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200155 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session4.getSessionId());
156 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("-1"));
157 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("0"));
158 assertThat(session4.getDeviceCapabilitiesSet(), containsInAnyOrder(
159 NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1.toArray()));
Sean Condond2c8d472017-02-17 17:09:39 +0000160 }
161
162 @AfterClass
163 public static void tearDown() throws Exception {
164 if (session1 != null) {
165 session1.close();
166 }
167 if (session2 != null) {
168 session2.close();
169 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200170 if (session3 != null) {
171 session3.close();
172 }
173 if (session4 != null) {
174 session4.close();
175 }
Sean Condond2c8d472017-02-17 17:09:39 +0000176
177 sshServerNetconf.stop();
Yuta HIGUCHI09ae3682017-08-14 18:56:54 -0700178 NetconfControllerImpl.netconfConnectTimeout = NetconfControllerImpl.DEFAULT_CONNECT_TIMEOUT_SECONDS;
179 NetconfControllerImpl.netconfIdleTimeout = NetconfControllerImpl.DEFAULT_IDLE_TIMEOUT_SECONDS;
180 NetconfControllerImpl.netconfReplyTimeout = NetconfControllerImpl.DEFAULT_REPLY_TIMEOUT_SECONDS;
Sean Condond2c8d472017-02-17 17:09:39 +0000181 }
182
183 @Test
184 public void testEditConfigRequest() {
185 log.info("Starting edit-config async");
186 assertNotNull("Incorrect sessionId", session1.getSessionId());
187 try {
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700188 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200189 session1.editConfig(DatastoreId.RUNNING,
190 null, SAMPLE_REQUEST));
191 } catch (NetconfException e) {
192 e.printStackTrace();
193 fail("NETCONF edit-config test failed: " + e.getMessage());
194 }
195 log.info("Finishing edit-config async");
196 }
197
198 @Test
199 public void testEditConfigRequestWithChunkedFraming() {
200 log.info("Starting edit-config async");
201 assertNotNull("Incorrect sessionId", session3.getSessionId());
202 try {
203 assertTrue("NETCONF edit-config command failed",
204 session3.editConfig(DatastoreId.RUNNING,
205 null, SAMPLE_REQUEST));
Sean Condond2c8d472017-02-17 17:09:39 +0000206 } catch (NetconfException e) {
207 e.printStackTrace();
208 fail("NETCONF edit-config test failed: " + e.getMessage());
209 }
210 log.info("Finishing edit-config async");
211 }
212
213 @Test
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700214 public void testEditConfigRequestWithOnlyNewConfiguration() {
215 log.info("Starting edit-config async");
216 assertNotNull("Incorrect sessionId", session1.getSessionId());
217 try {
218 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200219 session1.editConfig(NetconfSessionMinaImplTest.EDIT_CONFIG_REQUEST));
220 } catch (NetconfException e) {
221 e.printStackTrace();
222 fail("NETCONF edit-config test failed: " + e.getMessage());
223 }
224 log.info("Finishing edit-config async");
225 }
226
227 @Test
228 public void testEditConfigRequestWithOnlyNewConfigurationWithChunkedFraming() {
229 log.info("Starting edit-config async");
230 assertNotNull("Incorrect sessionId", session3.getSessionId());
231 try {
232 assertTrue("NETCONF edit-config command failed",
233 session3.editConfig(NetconfSessionMinaImplTest.EDIT_CONFIG_REQUEST));
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700234 } catch (NetconfException e) {
235 e.printStackTrace();
236 fail("NETCONF edit-config test failed: " + e.getMessage());
237 }
238 log.info("Finishing edit-config async");
239 }
240
241 @Test
242 public void testDeleteConfigRequestWithRunningTargetConfiguration() {
243 log.info("Starting delete-config async");
244 assertNotNull("Incorrect sessionId", session1.getSessionId());
245 try {
246 assertFalse("NETCONF delete-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200247 session1.deleteConfig(DatastoreId.RUNNING));
248 } catch (NetconfException e) {
249 e.printStackTrace();
250 fail("NETCONF delete-config test failed: " + e.getMessage());
251 }
252 log.info("Finishing delete-config async");
253 }
254
255 @Test
256 public void testDeleteConfigRequestWithRunningTargetConfigurationWithChunkedFraming() {
257 log.info("Starting delete-config async");
258 assertNotNull("Incorrect sessionId", session3.getSessionId());
259 try {
260 assertFalse("NETCONF delete-config command failed",
261 session3.deleteConfig(DatastoreId.RUNNING));
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700262 } catch (NetconfException e) {
263 e.printStackTrace();
264 fail("NETCONF delete-config test failed: " + e.getMessage());
265 }
266 log.info("Finishing delete-config async");
267 }
268
269 @Test
Sean Condond2c8d472017-02-17 17:09:39 +0000270 public void testCopyConfigRequest() {
271 log.info("Starting copy-config async");
272 assertNotNull("Incorrect sessionId", session1.getSessionId());
273 try {
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700274 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200275 session1.copyConfig(DatastoreId.RUNNING,
276 DatastoreId.CANDIDATE));
277 } catch (NetconfException e) {
278 e.printStackTrace();
279 fail("NETCONF copy-config test failed: " + e.getMessage());
280 }
281 log.info("Finishing copy-config async");
282 }
283
284 @Test
285 public void testCopyConfigRequestWithChunkedFraming() {
286 log.info("Starting copy-config async");
287 assertNotNull("Incorrect sessionId", session3.getSessionId());
288 try {
289 assertTrue("NETCONF copy-config command failed",
290 session3.copyConfig(DatastoreId.RUNNING,
291 DatastoreId.CANDIDATE));
Sean Condond2c8d472017-02-17 17:09:39 +0000292 } catch (NetconfException e) {
293 e.printStackTrace();
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700294 fail("NETCONF copy-config test failed: " + e.getMessage());
Sean Condond2c8d472017-02-17 17:09:39 +0000295 }
296 log.info("Finishing copy-config async");
297 }
298
299 @Test
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700300 public void testCopyConfigXml() {
301 log.info("Starting copy-config XML async");
302 assertNotNull("Incorrect sessionId", session1.getSessionId());
303 try {
304 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200305 session1.copyConfig(DatastoreId.RUNNING,
306 "<configuration><device-specific/></configuration>"));
307 } catch (NetconfException e) {
308 e.printStackTrace();
309 fail("NETCONF copy-config test failed: " + e.getMessage());
310 }
311 log.info("Finishing copy-config XML async");
312 }
313
314 @Test
315 public void testCopyConfigXmlWithChunkedFraming() {
316 log.info("Starting copy-config XML async");
317 assertNotNull("Incorrect sessionId", session3.getSessionId());
318 try {
319 assertTrue("NETCONF copy-config command failed",
320 session3.copyConfig(DatastoreId.RUNNING,
321 "<configuration><device-specific/></configuration>"));
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700322 } catch (NetconfException e) {
323 e.printStackTrace();
324 fail("NETCONF copy-config test failed: " + e.getMessage());
325 }
326 log.info("Finishing copy-config XML async");
327 }
328
329 // remove test when ready to dump bare XML String API.
330 @Test
331 public void testCopyConfigBareXml() {
332 log.info("Starting copy-config bare XML async");
333 assertNotNull("Incorrect sessionId", session1.getSessionId());
334 try {
335 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200336 session1.copyConfig(DatastoreId.RUNNING,
337 "<config>"
338 + "<configuration><device-specific/></configuration>"
339 + "</config>"));
340 } catch (NetconfException e) {
341 e.printStackTrace();
342 fail("NETCONF copy-config test failed: " + e.getMessage());
343 }
344 log.info("Finishing copy-config bare XML async");
345 }
346
347 @Test
348 public void testCopyConfigBareXmlWithChunkedFraming() {
349 log.info("Starting copy-config bare XML async");
350 assertNotNull("Incorrect sessionId", session3.getSessionId());
351 try {
352 assertTrue("NETCONF copy-config command failed",
353 session3.copyConfig(DatastoreId.RUNNING,
354 "<config>"
355 + "<configuration><device-specific/></configuration>"
356 + "</config>"));
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700357 } catch (NetconfException e) {
358 e.printStackTrace();
359 fail("NETCONF copy-config test failed: " + e.getMessage());
360 }
361 log.info("Finishing copy-config bare XML async");
362 }
363
364 @Test
Sean Condond2c8d472017-02-17 17:09:39 +0000365 public void testGetConfigRequest() {
366 log.info("Starting get-config async");
367 assertNotNull("Incorrect sessionId", session1.getSessionId());
368 try {
369 assertTrue("NETCONF get-config running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200370 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING,
371 SAMPLE_REQUEST)).matches());
Sean Condond2c8d472017-02-17 17:09:39 +0000372
373 assertTrue("NETCONF get-config candidate command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200374 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE,
375 SAMPLE_REQUEST)).matches());
376
377 } catch (NetconfException e) {
378 e.printStackTrace();
379 fail("NETCONF get-config test failed: " + e.getMessage());
380 }
381 log.info("Finishing get-config async");
382 }
383
384 @Test
385 public void testGetConfigRequestWithChunkedFraming() {
386 log.info("Starting get-config async");
387 assertNotNull("Incorrect sessionId", session3.getSessionId());
388 try {
389 assertTrue("NETCONF get-config running command failed. ",
390 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.getConfig(RUNNING,
391 SAMPLE_REQUEST)).matches());
392
393 assertTrue("NETCONF get-config candidate command failed. ",
394 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.getConfig(CANDIDATE,
395 SAMPLE_REQUEST)).matches());
Sean Condond2c8d472017-02-17 17:09:39 +0000396
397 } catch (NetconfException e) {
398 e.printStackTrace();
399 fail("NETCONF get-config test failed: " + e.getMessage());
400 }
401 log.info("Finishing get-config async");
402 }
403
404 @Test
405 public void testGetRequest() {
406 log.info("Starting get async");
407 assertNotNull("Incorrect sessionId", session1.getSessionId());
408 try {
409 assertTrue("NETCONF get running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200410 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST,
411 null)).matches());
412
413 } catch (NetconfException e) {
414 e.printStackTrace();
415 fail("NETCONF get test failed: " + e.getMessage());
416 }
417 log.info("Finishing get async");
418 }
419
420 @Test
421 public void testGetRequestWithChunkedFraming() {
422 log.info("Starting get async");
423 assertNotNull("Incorrect sessionId", session3.getSessionId());
424 try {
425 assertTrue("NETCONF get running command failed. ",
426 NetconfSessionMinaImplTest.GET_REPLY_PATTERN.matcher(session3.get(SAMPLE_REQUEST, null)).matches());
Sean Condond2c8d472017-02-17 17:09:39 +0000427
428 } catch (NetconfException e) {
429 e.printStackTrace();
430 fail("NETCONF get test failed: " + e.getMessage());
431 }
432 log.info("Finishing get async");
433 }
434
435 @Test
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700436 public void testLockRequest() {
437 log.info("Starting lock async");
438 assertNotNull("Incorrect sessionId", session1.getSessionId());
439 try {
440 assertTrue("NETCONF lock request failed", session1.lock());
441 } catch (NetconfException e) {
442 e.printStackTrace();
443 fail("NETCONF lock test failed: " + e.getMessage());
444 }
445 log.info("Finishing lock async");
446 }
447
448 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200449 public void testLockRequestWithChunkedFraming() {
450 log.info("Starting lock async");
451 assertNotNull("Incorrect sessionId", session3.getSessionId());
452 try {
453 assertTrue("NETCONF lock request failed", session3.lock());
454 } catch (NetconfException e) {
455 e.printStackTrace();
456 fail("NETCONF lock test failed: " + e.getMessage());
457 }
458 log.info("Finishing lock async");
459 }
460
461 @Test
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700462 public void testUnLockRequest() {
463 log.info("Starting unlock async");
464 assertNotNull("Incorrect sessionId", session1.getSessionId());
465 try {
466 assertTrue("NETCONF unlock request failed", session1.unlock());
467 } catch (NetconfException e) {
468 e.printStackTrace();
469 fail("NETCONF unlock test failed: " + e.getMessage());
470 }
471 log.info("Finishing unlock async");
472 }
473
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200474 @Test
475 public void testUnLockRequestWithChunkedFraming() {
476 log.info("Starting unlock async");
477 assertNotNull("Incorrect sessionId", session3.getSessionId());
478 try {
479 assertTrue("NETCONF unlock request failed", session3.unlock());
480 } catch (NetconfException e) {
481 e.printStackTrace();
482 fail("NETCONF unlock test failed: " + e.getMessage());
483 }
484 log.info("Finishing unlock async");
485 }
486
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700487
488 @Test
Sean Condond2c8d472017-02-17 17:09:39 +0000489 public void testConcurrentSameSessionAccess() throws InterruptedException {
Andrei Mihaescuac542ca2017-03-26 21:36:25 +0300490 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
491 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session1, RUNNING, "startup");
Sean Condond2c8d472017-02-17 17:09:39 +0000492
Aaron Kruglikov72db6422017-02-13 12:16:51 -0800493 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
494 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
Sean Condond2c8d472017-02-17 17:09:39 +0000495
496 ExecutorService executor = Executors.newFixedThreadPool(2);
497 log.info("Starting concurrent execution of copy-config through same session");
498 executor.execute(futureCopyConfig1);
499 executor.execute(futureCopyConfig2);
500
501 int count = 0;
502 while (count < 10) {
503 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
504 executor.shutdown();
505 log.info("Finished concurrent same session execution");
506 return;
507 }
508 Thread.sleep(100L);
509 count++;
510 }
511 fail("NETCONF test failed to complete.");
512 }
513
514 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200515 public void testConcurrentSameSessionAccessWithChunkedFraming() throws InterruptedException {
516 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
517 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session3, RUNNING, "startup");
518
519 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
520 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
521
522 ExecutorService executor = Executors.newFixedThreadPool(2);
523 log.info("Starting concurrent execution of copy-config through same session");
524 executor.execute(futureCopyConfig1);
525 executor.execute(futureCopyConfig2);
526
527 int count = 0;
528 while (count < 10) {
529 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
530 executor.shutdown();
531 log.info("Finished concurrent same session execution");
532 return;
533 }
534 Thread.sleep(100L);
535 count++;
536 }
537 fail("NETCONF test failed to complete.");
538 }
539
540 @Test
Sean Condond2c8d472017-02-17 17:09:39 +0000541 public void test2SessionAccess() throws InterruptedException {
Andrei Mihaescuac542ca2017-03-26 21:36:25 +0300542 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
543 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session2, RUNNING, "candidate");
Sean Condond2c8d472017-02-17 17:09:39 +0000544
Aaron Kruglikov72db6422017-02-13 12:16:51 -0800545 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
546 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
Sean Condond2c8d472017-02-17 17:09:39 +0000547
548 ExecutorService executor = Executors.newFixedThreadPool(2);
549 log.info("Starting concurrent execution of copy-config through 2 different sessions");
550 executor.execute(futureCopySession1);
551 executor.execute(futureCopySession2);
552
553 int count = 0;
554 while (count < 10) {
555 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
556 executor.shutdown();
557 log.info("Finished concurrent 2 session execution");
558 return;
559 }
560 Thread.sleep(100L);
561 count++;
562 }
563 fail("NETCONF test failed to complete.");
564 }
565
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200566 @Test
567 public void test2SessionAccessWithChunkedFraming() throws InterruptedException {
568 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
569 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session4, RUNNING, "candidate");
Sean Condond2c8d472017-02-17 17:09:39 +0000570
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200571 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
572 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
573
574 ExecutorService executor = Executors.newFixedThreadPool(2);
575 log.info("Starting concurrent execution of copy-config through 2 different sessions");
576 executor.execute(futureCopySession1);
577 executor.execute(futureCopySession2);
578
579 int count = 0;
580 while (count < 10) {
581 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
582 executor.shutdown();
583 log.info("Finished concurrent 2 session execution");
584 return;
585 }
586 Thread.sleep(100L);
587 count++;
588 }
589 fail("NETCONF test failed to complete.");
590 }
591
Sean Condon54d82432017-07-26 22:27:25 +0100592 @Test
593 public void testSessionTimeouts() {
594 assertTrue("SSH Client wrong", session1 instanceof NetconfSessionImpl);
595 assertEquals("Timeout wrong", 5, session1.timeoutConnectSec());
596 assertEquals("Timeout wrong", 5, session1.timeoutReplySec());
597 assertEquals("Timeout wrong", 5, session1.timeoutIdleSec());
598
599 assertTrue("SSH Client wrong", session2 instanceof NetconfSessionMinaImpl);
600 assertEquals("Timeout wrong", 11, session2.timeoutConnectSec());
601 assertEquals("Timeout wrong", 10, session2.timeoutReplySec());
602 assertEquals("Timeout wrong", 12, session2.timeoutIdleSec());
603 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200604
605 public static String getTestHelloReply(Optional<Long> sessionId, boolean useChunkedFraming) {
606 if (useChunkedFraming) {
607 return getTestHelloReply(NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES_1_1, sessionId);
608 } else {
609 return getTestHelloReply(NetconfSessionMinaImplTest.DEFAULT_CAPABILITIES, sessionId);
610 }
Aaron Kruglikov72db6422017-02-13 12:16:51 -0800611 }
612
613 public static String getTestHelloReply(Collection<String> capabilities, Optional<Long> sessionId) {
Sean Condond2c8d472017-02-17 17:09:39 +0000614 StringBuffer sb = new StringBuffer();
615
616 sb.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
617 sb.append("<capabilities>");
Aaron Kruglikov72db6422017-02-13 12:16:51 -0800618 capabilities.forEach(capability -> {
619 sb.append("<capability>").append(capability).append("</capability>");
620 });
Sean Condond2c8d472017-02-17 17:09:39 +0000621 sb.append("</capabilities>");
622 if (sessionId.isPresent()) {
623 sb.append("<session-id>");
624 sb.append(sessionId.get().toString());
625 sb.append("</session-id>");
626 }
627 sb.append("</hello>");
628
629 return sb.toString();
630 }
631
632 public static String getOkReply(Optional<Integer> messageId) {
633 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
634 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
635 if (messageId.isPresent()) {
636 sb.append("message-id=\"");
637 sb.append(String.valueOf(messageId.get()));
638 sb.append("\">");
639 }
640 sb.append("<ok/>");
641 sb.append("</rpc-reply>");
642 return sb.toString();
643 }
644
645 public static String getGetReply(Optional<Integer> messageId) {
646 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
647 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
648 if (messageId.isPresent()) {
649 sb.append("message-id=\"");
650 sb.append(String.valueOf(messageId.get()));
651 sb.append("\">");
652 }
653 sb.append("<data>\n");
654 sb.append(SAMPLE_REQUEST);
655 sb.append("</data>\n");
656 sb.append("</rpc-reply>");
657 return sb.toString();
658 }
659
660 public static final Pattern HELLO_REQ_PATTERN =
661 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200662 + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
663 + "( *)(<capabilities>)\\R?"
664 + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
665 + "( *)(</capabilities>)\\R?"
666 + "(</hello>)\\R? *",
667 Pattern.DOTALL);
668
669 public static final Pattern HELLO_REQ_PATTERN_1_1 =
Sean Condon2d647172017-09-19 12:29:13 +0100670 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200671 + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
672 + "( *)(<capabilities>)\\R?"
673 + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
674 + "( *)(<capability>urn:ietf:params:netconf:base:1.1</capability>)\\R?"
675 + "( *)(</capabilities>)\\R?"
676 + "(</hello>)\\R? *",
Sean Condond2c8d472017-02-17 17:09:39 +0000677 Pattern.DOTALL);
678
679 public static final Pattern EDIT_CONFIG_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100680 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000681 + "(<rpc message-id=\")[0-9]*(\") *(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
682 + "(<edit-config>)\\R?"
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700683 + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200684 + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
685 + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000686 + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
687 + ".*"
688 + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
689
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700690
691 public static final Pattern LOCK_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100692 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200693 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
694 + "message-id=\")[0-9]*(\">)\\R?"
695 + "(<lock>)\\R?"
696 + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
697 + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
698 + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
699 + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700700
701 public static final Pattern UNLOCK_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100702 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200703 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
704 + "message-id=\")[0-9]*(\">)\\R?"
705 + "(<unlock>)\\R?"
706 + "(<target>\\R?((<" + DatastoreId.CANDIDATE.toString() + "/>)|"
707 + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
708 + "(<" + DatastoreId.STARTUP.toString() + "/>))\\R?</target>)\\R?"
709 + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700710
Sean Condond2c8d472017-02-17 17:09:39 +0000711 public static final Pattern COPY_CONFIG_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100712 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000713 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
714 + "(<copy-config>)\\R?"
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700715 + "(<target>\\R?"
716 + "("
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200717 + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
718 + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
719 + "(<" + DatastoreId.STARTUP.toString() + "/>)"
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700720 + ")\\R?"
721 + "</target>)\\R?"
722 + "(<source>)\\R?"
723 + "("
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200724 + "(<config>)(.*)(</config>)|"
725 + "(<" + DatastoreId.CANDIDATE.toString() + "/>)|"
726 + "(<" + DatastoreId.RUNNING.toString() + "/>)|"
727 + "(<" + DatastoreId.STARTUP.toString() + "/>)"
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700728 + ")\\R?"
729 + "(</source>)\\R?"
730 + "(</copy-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Sean Condond2c8d472017-02-17 17:09:39 +0000731
732 public static final Pattern GET_CONFIG_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100733 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000734 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
Shivani Vaidya48df84e2017-04-13 13:48:17 -0700735 + "(<get-config>)\\R?" + "(<source>)\\R?((<"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200736 + DatastoreId.CANDIDATE.toString()
737 + "/>)|(<" + DatastoreId.RUNNING.toString()
738 + "/>)|(<" + DatastoreId.STARTUP.toString()
739 + "/>))\\R?(</source>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000740 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
741 + "(</get-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
742
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200743
Sean Condond2c8d472017-02-17 17:09:39 +0000744
745 public static final Pattern GET_REQ_PATTERN =
Sean Condon2d647172017-09-19 12:29:13 +0100746 Pattern.compile("(<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>)\\R?"
Sean Condond2c8d472017-02-17 17:09:39 +0000747 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
748 + "(<get>)\\R?"
749 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
750 + "(</get>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
751
752 public class NCCopyConfigCallable implements Callable<Boolean> {
753 private NetconfSession session;
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700754 private DatastoreId target;
Sean Condond2c8d472017-02-17 17:09:39 +0000755 private String source;
756
Yuta HIGUCHI89111d92017-05-04 11:29:17 -0700757 public NCCopyConfigCallable(NetconfSession session, DatastoreId target, String source) {
Sean Condond2c8d472017-02-17 17:09:39 +0000758 this.session = session;
759 this.target = target;
760 this.source = source;
761 }
762
763 @Override
764 public Boolean call() throws Exception {
765 return session.copyConfig(target, source);
766 }
767 }
Sean Condon54d82432017-07-26 22:27:25 +0100768}