blob: ada609b2dd7fca642d7a6c15b003d9f5183c4a10 [file] [log] [blame]
Andrea Campanella7bbe7b12017-05-03 16:03:38 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Andrea Campanella7bbe7b12017-05-03 16:03:38 -07003 *
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 */
16package org.onosproject.netconf.ctl.impl;
17
18import com.google.common.collect.ImmutableList;
19import org.apache.sshd.common.NamedFactory;
20import org.apache.sshd.server.Command;
21import org.apache.sshd.server.SshServer;
22import org.apache.sshd.server.auth.password.PasswordAuthenticator;
23import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
24import org.apache.sshd.server.session.ServerSession;
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070025import org.bouncycastle.jce.provider.BouncyCastleProvider;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070026import org.junit.AfterClass;
27import org.junit.BeforeClass;
28import org.junit.Test;
29import org.onlab.junit.TestTools;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070030import org.onosproject.netconf.NetconfDeviceInfo;
31import org.onosproject.netconf.NetconfException;
32import org.onosproject.netconf.NetconfSession;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020033import org.onosproject.netconf.DatastoreId;
34import org.onlab.packet.Ip4Address;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070035import org.slf4j.Logger;
36import org.slf4j.LoggerFactory;
37
38import java.io.File;
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070039import java.security.Security;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070040import java.util.Arrays;
41import java.util.Collection;
42import java.util.List;
43import java.util.Optional;
44import java.util.concurrent.Callable;
45import java.util.concurrent.ExecutorService;
46import java.util.concurrent.Executors;
47import java.util.concurrent.FutureTask;
48import java.util.regex.Pattern;
49
50import static org.hamcrest.Matchers.containsInAnyOrder;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020051import static org.junit.Assert.assertTrue;
52import static org.junit.Assert.assertThat;
53import static org.junit.Assert.assertNotNull;
54import static org.junit.Assert.fail;
55import static org.junit.Assert.assertFalse;
56import static org.onosproject.netconf.DatastoreId.CANDIDATE;
57import static org.onosproject.netconf.DatastoreId.RUNNING;
58import static org.onosproject.netconf.DatastoreId.STARTUP;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070059
60/**
61 * Unit tests for NetconfSession.
62 * <p>
63 * 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 NetconfSessionMinaImplTest {
67 private static final Logger log = LoggerFactory
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070068 .getLogger(NetconfSessionMinaImplTest.class);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070069
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070070 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";
73
74 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\">"
79 + "<some-child-element/>"
80 + "</some-yang-element>";
81
Kamil Stasiak9f59f442017-05-02 11:02:24 +020082 protected static final String EDIT_CONFIG_REQUEST =
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070083 "<?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
93 static final List<String> DEFAULT_CAPABILITIES = ImmutableList.<String>builder()
94 .add("urn:ietf:params:netconf:base:1.0")
Kamil Stasiak9f59f442017-05-02 11:02:24 +020095 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
96 .add("urn:ietf:params:netconf:capability:candidate:1.0")
97 .add("urn:ietf:params:netconf:capability:startup:1.0")
98 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
99 .add("urn:ietf:params:netconf:capability:interleave:1.0")
100 .add("urn:ietf:params:netconf:capability:notification:1.0")
101 .add("urn:ietf:params:netconf:capability:validate:1.0")
102 .add("urn:ietf:params:netconf:capability:validate:1.1")
103 .build();
104
105 static final List<String> DEFAULT_CAPABILITIES_1_1 = ImmutableList.<String>builder()
106 .add("urn:ietf:params:netconf:base:1.0")
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700107 .add("urn:ietf:params:netconf:base:1.1")
108 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
109 .add("urn:ietf:params:netconf:capability:candidate:1.0")
110 .add("urn:ietf:params:netconf:capability:startup:1.0")
111 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
112 .add("urn:ietf:params:netconf:capability:interleave:1.0")
113 .add("urn:ietf:params:netconf:capability:notification:1.0")
114 .add("urn:ietf:params:netconf:capability:validate:1.0")
115 .add("urn:ietf:params:netconf:capability:validate:1.1")
116 .build();
117
118
119 private static NetconfSession session1;
120 private static NetconfSession session2;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200121 private static NetconfSession session3;
122 private static NetconfSession session4;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700123 private static SshServer sshServerNetconf;
124
125 @BeforeClass
126 public static void setUp() throws Exception {
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700127 Security.addProvider(new BouncyCastleProvider());
128 int portNumber = TestTools.findAvailablePort(50830);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700129 sshServerNetconf = SshServer.setUpDefaultServer();
130 sshServerNetconf.setPasswordAuthenticator(
131 new PasswordAuthenticator() {
132 @Override
133 public boolean authenticate(
134 String username,
135 String password,
136 ServerSession session) {
137 return TEST_USERNAME.equals(username) && TEST_PASSWORD.equals(password);
138 }
139 });
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700140 sshServerNetconf.setPort(portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700141 SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
142 provider.setFile(new File(TEST_SERFILE));
143 sshServerNetconf.setKeyPairProvider(provider);
144 sshServerNetconf.setSubsystemFactories(
145 Arrays.<NamedFactory<Command>>asList(new NetconfSshdTestSubsystem.Factory()));
146 sshServerNetconf.open();
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700147 log.info("SSH Server opened on port {}", portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700148
149 NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo(
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700150 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700151
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200152 session1 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700153 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session1.getSessionId());
154 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("-1"));
155 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("0"));
156 assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
157
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200158 session2 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700159 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session2.getSessionId());
160 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("-1"));
161 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("0"));
162 assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200163
164 session3 = new NetconfSessionMinaImpl(deviceInfo);
165 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session3.getSessionId());
166 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("-1"));
167 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("0"));
168 assertThat(session3.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
169
170 session4 = new NetconfSessionMinaImpl(deviceInfo);
171 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session4.getSessionId());
172 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("-1"));
173 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("0"));
174 assertThat(session4.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700175 }
176
177 @AfterClass
178 public static void tearDown() throws Exception {
179 if (session1 != null) {
180 session1.close();
181 }
182 if (session2 != null) {
183 session2.close();
184 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200185 if (session3 != null) {
186 session3.close();
187 }
188 if (session4 != null) {
189 session4.close();
190 }
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700191
192 sshServerNetconf.stop();
193 }
194
195 @Test
196 public void testEditConfigRequest() {
197 log.info("Starting edit-config async");
198 assertNotNull("Incorrect sessionId", session1.getSessionId());
199 try {
200 assertTrue("NETCONF edit-config command failed",
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700201 session1.editConfig(RUNNING,
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200202 null, SAMPLE_REQUEST));
203 } catch (NetconfException e) {
204 e.printStackTrace();
205 fail("NETCONF edit-config test failed: " + e.getMessage());
206 }
207 log.info("Finishing edit-config async");
208 }
209
210 @Test
211 public void testEditConfigRequestWithChunkedFraming() {
212 log.info("Starting edit-config async");
213
214 assertNotNull("Incorrect sessionId", session3.getSessionId());
215 try {
216 assertTrue("NETCONF edit-config command failed",
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700217 session3.editConfig(RUNNING,
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200218 null, SAMPLE_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700219 } catch (NetconfException e) {
220 e.printStackTrace();
221 fail("NETCONF edit-config test failed: " + e.getMessage());
222 }
223 log.info("Finishing edit-config async");
224 }
225
226 @Test
227 public void testEditConfigRequestWithOnlyNewConfiguration() {
228 log.info("Starting edit-config async");
229 assertNotNull("Incorrect sessionId", session1.getSessionId());
230 try {
231 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200232 session1.editConfig(EDIT_CONFIG_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700233 } catch (NetconfException e) {
234 e.printStackTrace();
235 fail("NETCONF edit-config test failed: " + e.getMessage());
236 }
237 log.info("Finishing edit-config async");
238 }
239
240 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200241 public void testEditConfigRequestWithOnlyNewConfigurationWithChunkedFraming() {
242 log.info("Starting edit-config async");
243 assertNotNull("Incorrect sessionId", session3.getSessionId());
244 try {
245 assertTrue("NETCONF edit-config command failed",
246 session3.editConfig(EDIT_CONFIG_REQUEST));
247 } catch (NetconfException e) {
248 e.printStackTrace();
249 fail("NETCONF edit-config test failed: " + e.getMessage());
250 }
251 log.info("Finishing edit-config async");
252 }
253
254 @Test
255 public void testDeleteConfigRequestWithRunningDatastoreIdDuration() {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700256 log.info("Starting delete-config async");
257 assertNotNull("Incorrect sessionId", session1.getSessionId());
258 try {
259 assertFalse("NETCONF delete-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200260 session1.deleteConfig(RUNNING));
261 } catch (NetconfException e) {
262 e.printStackTrace();
263 fail("NETCONF delete-config test failed: " + e.getMessage());
264 }
265 log.info("Finishing delete-config async");
266 }
267
268 @Test
269 public void testDeleteConfigRequestWithRunningDatastoreIdDurationWithChunkedFraming() {
270 log.info("Starting delete-config async");
271 assertNotNull("Incorrect sessionId", session3.getSessionId());
272 try {
273 assertFalse("NETCONF delete-config command failed",
274 session3.deleteConfig(RUNNING));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700275 } catch (NetconfException e) {
276 e.printStackTrace();
277 fail("NETCONF delete-config test failed: " + e.getMessage());
278 }
279 log.info("Finishing delete-config async");
280 }
281
282 @Test
283 public void testCopyConfigRequest() {
284 log.info("Starting copy-config async");
285 assertNotNull("Incorrect sessionId", session1.getSessionId());
286 try {
287 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200288 session1.copyConfig(RUNNING.toString(),
289 "candidate"));
290 } catch (NetconfException e) {
291 e.printStackTrace();
292 fail("NETCONF edit-config test failed: " + e.getMessage());
293 }
294 log.info("Finishing copy-config async");
295 }
296
297 @Test
298 public void testCopyConfigRequestWithChunkedFraming() {
299 log.info("Starting copy-config async");
300 assertNotNull("Incorrect sessionId", session3.getSessionId());
301 try {
302 assertTrue("NETCONF copy-config command failed",
303 session3.copyConfig(RUNNING.toString(),
304 "candidate"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700305 } catch (NetconfException e) {
306 e.printStackTrace();
307 fail("NETCONF edit-config test failed: " + e.getMessage());
308 }
309 log.info("Finishing copy-config async");
310 }
311
312 @Test
313 public void testGetConfigRequest() {
314 log.info("Starting get-config async");
315 assertNotNull("Incorrect sessionId", session1.getSessionId());
316 try {
317 assertTrue("NETCONF get-config running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200318 GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700319
320 assertTrue("NETCONF get-config candidate command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200321 GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
322
323 } catch (NetconfException e) {
324 e.printStackTrace();
325 fail("NETCONF get-config test failed: " + e.getMessage());
326 }
327 log.info("Finishing get-config async");
328 }
329
330 @Test
331 public void testGetConfigRequestWithChunkedFraming() {
332 log.info("Starting get-config async");
333 assertNotNull("Incorrect sessionId", session3.getSessionId());
334 try {
335 assertTrue("NETCONF get-config running command failed. ",
336 GET_REPLY_PATTERN.matcher(session3.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
337
338 assertTrue("NETCONF get-config candidate command failed. ",
339 GET_REPLY_PATTERN.matcher(session3.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700340
341 } catch (NetconfException e) {
342 e.printStackTrace();
343 fail("NETCONF get-config test failed: " + e.getMessage());
344 }
345 log.info("Finishing get-config async");
346 }
347
348 @Test
349 public void testGetRequest() {
350 log.info("Starting get async");
351 assertNotNull("Incorrect sessionId", session1.getSessionId());
352 try {
353 assertTrue("NETCONF get running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200354 GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST, null)).matches());
355
356 } catch (NetconfException e) {
357 e.printStackTrace();
358 fail("NETCONF get test failed: " + e.getMessage());
359 }
360 log.info("Finishing get async");
361 }
362
363 @Test
364 public void testGetRequestWithChunkedFraming() {
365 log.info("Starting get async");
366 assertNotNull("Incorrect sessionId", session3.getSessionId());
367 try {
368 assertTrue("NETCONF get running command failed. ",
369 GET_REPLY_PATTERN.matcher(session3.get(SAMPLE_REQUEST, null)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700370
371 } catch (NetconfException e) {
372 e.printStackTrace();
373 fail("NETCONF get test failed: " + e.getMessage());
374 }
375 log.info("Finishing get async");
376 }
377
378 @Test
379 public void testLockRequest() {
380 log.info("Starting lock async");
381 assertNotNull("Incorrect sessionId", session1.getSessionId());
382 try {
383 assertTrue("NETCONF lock request failed", session1.lock());
384 } catch (NetconfException e) {
385 e.printStackTrace();
386 fail("NETCONF lock test failed: " + e.getMessage());
387 }
388 log.info("Finishing lock async");
389 }
390
391 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200392 public void testLockRequestWithChunkedFraming() {
393 log.info("Starting lock async");
394 assertNotNull("Incorrect sessionId", session3.getSessionId());
395 try {
396 assertTrue("NETCONF lock request failed", session3.lock());
397 } catch (NetconfException e) {
398 e.printStackTrace();
399 fail("NETCONF lock test failed: " + e.getMessage());
400 }
401 log.info("Finishing lock async");
402 }
403
404 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700405 public void testUnLockRequest() {
406 log.info("Starting unlock async");
407 assertNotNull("Incorrect sessionId", session1.getSessionId());
408 try {
409 assertTrue("NETCONF unlock request failed", session1.unlock());
410 } catch (NetconfException e) {
411 e.printStackTrace();
412 fail("NETCONF unlock test failed: " + e.getMessage());
413 }
414 log.info("Finishing unlock async");
415 }
416
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200417 @Test
418 public void testUnLockRequestWithChunkedFraming() {
419 log.info("Starting unlock async");
420 assertNotNull("Incorrect sessionId", session3.getSessionId());
421 try {
422 assertTrue("NETCONF unlock request failed", session3.unlock());
423 } catch (NetconfException e) {
424 e.printStackTrace();
425 fail("NETCONF unlock test failed: " + e.getMessage());
426 }
427 log.info("Finishing unlock async");
428 }
429
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700430
431 @Test
432 public void testConcurrentSameSessionAccess() throws InterruptedException {
433 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
434 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session1, RUNNING, "startup");
435
436 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
437 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
438
439 ExecutorService executor = Executors.newFixedThreadPool(2);
440 log.info("Starting concurrent execution of copy-config through same session");
441 executor.execute(futureCopyConfig1);
442 executor.execute(futureCopyConfig2);
443
444 int count = 0;
445 while (count < 10) {
446 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
447 executor.shutdown();
448 log.info("Finished concurrent same session execution");
449 return;
450 }
451 Thread.sleep(100L);
452 count++;
453 }
454 fail("NETCONF test failed to complete.");
455 }
456
457 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200458 public void testConcurrentSameSessionAccessWithChunkedFraming() throws InterruptedException {
459 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
460 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session3, RUNNING, "startup");
461
462 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
463 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
464
465 ExecutorService executor = Executors.newFixedThreadPool(2);
466 log.info("Starting concurrent execution of copy-config through same session");
467 executor.execute(futureCopyConfig1);
468 executor.execute(futureCopyConfig2);
469
470 int count = 0;
471 while (count < 10) {
472 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
473 executor.shutdown();
474 log.info("Finished concurrent same session execution");
475 return;
476 }
477 Thread.sleep(100L);
478 count++;
479 }
480 fail("NETCONF test failed to complete.");
481 }
482
483 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700484 public void test2SessionAccess() throws InterruptedException {
485 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
486 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session2, RUNNING, "candidate");
487
488 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
489 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
490
491 ExecutorService executor = Executors.newFixedThreadPool(2);
492 log.info("Starting concurrent execution of copy-config through 2 different sessions");
493 executor.execute(futureCopySession1);
494 executor.execute(futureCopySession2);
495
496 int count = 0;
497 while (count < 10) {
498 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
499 executor.shutdown();
500 log.info("Finished concurrent 2 session execution");
501 return;
502 }
503 Thread.sleep(100L);
504 count++;
505 }
506 fail("NETCONF test failed to complete.");
507 }
508
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200509 @Test
510 public void test2SessionAccessWithChunkedFraming() throws InterruptedException {
511 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
512 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session4, RUNNING, "candidate");
513
514 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
515 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
516
517 ExecutorService executor = Executors.newFixedThreadPool(2);
518 log.info("Starting concurrent execution of copy-config through 2 different sessions");
519 executor.execute(futureCopySession1);
520 executor.execute(futureCopySession2);
521
522 int count = 0;
523 while (count < 10) {
524 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
525 executor.shutdown();
526 log.info("Finished concurrent 2 session execution");
527 return;
528 }
529 Thread.sleep(100L);
530 count++;
531 }
532 fail("NETCONF test failed to complete.");
533 }
534
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700535
536 public static String getTestHelloReply(Optional<Long> sessionId) {
537 return getTestHelloReply(DEFAULT_CAPABILITIES, sessionId);
538 }
539
540 public static String getTestHelloReply(Collection<String> capabilities, Optional<Long> sessionId) {
541 StringBuffer sb = new StringBuffer();
542
543 sb.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
544 sb.append("<capabilities>");
545 capabilities.forEach(capability -> {
546 sb.append("<capability>").append(capability).append("</capability>");
547 });
548 sb.append("</capabilities>");
549 if (sessionId.isPresent()) {
550 sb.append("<session-id>");
551 sb.append(sessionId.get().toString());
552 sb.append("</session-id>");
553 }
554 sb.append("</hello>");
555
556 return sb.toString();
557 }
558
559 public static String getOkReply(Optional<Integer> messageId) {
560 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
561 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
562 if (messageId.isPresent()) {
563 sb.append("message-id=\"");
564 sb.append(String.valueOf(messageId.get()));
565 sb.append("\">");
566 }
567 sb.append("<ok/>");
568 sb.append("</rpc-reply>");
569 return sb.toString();
570 }
571
572 public static String getGetReply(Optional<Integer> messageId) {
573 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
574 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
575 if (messageId.isPresent()) {
576 sb.append("message-id=\"");
577 sb.append(String.valueOf(messageId.get()));
578 sb.append("\">");
579 }
580 sb.append("<data>\n");
581 sb.append(SAMPLE_REQUEST);
582 sb.append("</data>\n");
583 sb.append("</rpc-reply>");
584 return sb.toString();
585 }
586
587 public static final Pattern HELLO_REQ_PATTERN =
588 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200589 + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
590 + "( *)(<capabilities>)\\R?"
591 + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
592 + "( *)(<capability>urn:ietf:params:netconf:base:1.1</capability>)\\R?"
593 + "( *)(</capabilities>)\\R?"
594 + "(</hello>)\\R? *",
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700595 Pattern.DOTALL);
596
597 public static final Pattern EDIT_CONFIG_REQ_PATTERN =
598 Pattern.compile("(<\\?xml).*"
599 + "(<rpc message-id=\")[0-9]*(\") *(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
600 + "(<edit-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200601 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
602 + "(<" + RUNNING.toString() + "/>)|"
603 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700604 + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
605 + ".*"
606 + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
607
608
609 public static final Pattern LOCK_REQ_PATTERN =
610 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200611 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
612 + "message-id=\")[0-9]*(\">)\\R?"
613 + "(<lock>)\\R?"
614 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
615 + "(<" + RUNNING.toString() + "/>)|"
616 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
617 + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700618
619 public static final Pattern UNLOCK_REQ_PATTERN =
620 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200621 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
622 + "message-id=\")[0-9]*(\">)\\R?"
623 + "(<unlock>)\\R?"
624 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
625 + "(<" + RUNNING.toString() + "/>)|"
626 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
627 + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700628
629 public static final Pattern COPY_CONFIG_REQ_PATTERN =
630 Pattern.compile("(<\\?xml).*"
631 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
632 + "(<copy-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200633 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
634 + "(<" + RUNNING.toString() + "/>)|"
635 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
636 + "(<source>)\\R?(<config>)(("
637 + CANDIDATE.toString() + ")|("
638 + RUNNING.toString() + ")|("
639 + STARTUP.toString()
640 + "))(</config>)\\R?(</source>)\\R?"
641 + "(</copy-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700642
643 public static final Pattern GET_CONFIG_REQ_PATTERN =
644 Pattern.compile("(<\\?xml).*"
645 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
646 + "(<get-config>)\\R?" + "(<source>)\\R?((<"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200647 + CANDIDATE.toString()
648 + "/>)|(<" + RUNNING.toString()
649 + "/>)|(<" + STARTUP.toString()
650 + "/>))\\R?(</source>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700651 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
652 + "(</get-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
653
654 public static final Pattern GET_REPLY_PATTERN =
655 Pattern.compile("(<\\?xml).*"
656 + "(<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
657 + "(<data>).*(</data>)\\R?"
658 + "(</rpc-reply>)\\R?", Pattern.DOTALL);
659
660 public static final Pattern GET_REQ_PATTERN =
661 Pattern.compile("(<\\?xml).*"
662 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
663 + "(<get>)\\R?"
664 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
665 + "(</get>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
666
667 public class NCCopyConfigCallable implements Callable<Boolean> {
668 private NetconfSession session;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200669 private DatastoreId target;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700670 private String source;
671
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200672 public NCCopyConfigCallable(NetconfSession session, DatastoreId target, String source) {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700673 this.session = session;
674 this.target = target;
675 this.source = source;
676 }
677
678 @Override
679 public Boolean call() throws Exception {
680 return session.copyConfig(target, source);
681 }
682 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200683}