blob: 8fd4a86dae0c7de144f6e7042ec269f73d9b716a [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;
25import org.junit.AfterClass;
26import org.junit.BeforeClass;
27import org.junit.Test;
28import org.onlab.junit.TestTools;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070029import org.onosproject.netconf.NetconfDeviceInfo;
30import org.onosproject.netconf.NetconfException;
31import org.onosproject.netconf.NetconfSession;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020032import org.onosproject.netconf.DatastoreId;
33import org.onlab.packet.Ip4Address;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070034import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import java.io.File;
38import java.util.Arrays;
39import java.util.Collection;
40import java.util.List;
41import java.util.Optional;
42import java.util.concurrent.Callable;
43import java.util.concurrent.ExecutorService;
44import java.util.concurrent.Executors;
45import java.util.concurrent.FutureTask;
46import java.util.regex.Pattern;
47
48import static org.hamcrest.Matchers.containsInAnyOrder;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020049import static org.junit.Assert.assertTrue;
50import static org.junit.Assert.assertThat;
51import static org.junit.Assert.assertNotNull;
52import static org.junit.Assert.fail;
53import static org.junit.Assert.assertFalse;
54import static org.onosproject.netconf.DatastoreId.CANDIDATE;
55import static org.onosproject.netconf.DatastoreId.RUNNING;
56import static org.onosproject.netconf.DatastoreId.STARTUP;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070057
58/**
59 * Unit tests for NetconfSession.
60 * <p>
61 * Sets up an SSH Server with Apache SSHD and connects to it using 2 clients
62 * Truly verifies that the NETCONF flows are compliant with a NETCONF server.
63 */
64public class NetconfSessionMinaImplTest {
65 private static final Logger log = LoggerFactory
66 .getLogger(NetconfStreamThread.class);
67
68 private static final int PORT_NUMBER = TestTools.findAvailablePort(50830);
69 private static final String TEST_USERNAME = "netconf";
70 private static final String TEST_PASSWORD = "netconf123";
71 private static final String TEST_HOSTNAME = "127.0.0.1";
72
73 private static final String TEST_SERFILE =
74 System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + "testkey.ser";
75
76 private static final String SAMPLE_REQUEST =
77 "<some-yang-element xmlns=\"some-namespace\">"
78 + "<some-child-element/>"
79 + "</some-yang-element>";
80
Kamil Stasiak9f59f442017-05-02 11:02:24 +020081 protected static final String EDIT_CONFIG_REQUEST =
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070082 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc message-id=\"6\" "
83 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
84 + "<edit-config>\n"
85 + "<target><running/></target>\n"
86 + "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
87 + "<some-yang-element xmlns=\"some-namespace\">"
88 + "<some-child-element/></some-yang-element></config>\n"
89 + "</edit-config>\n"
90 + "</rpc>]]>]]>";
91
92 static final List<String> DEFAULT_CAPABILITIES = ImmutableList.<String>builder()
93 .add("urn:ietf:params:netconf:base:1.0")
Kamil Stasiak9f59f442017-05-02 11:02:24 +020094 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
95 .add("urn:ietf:params:netconf:capability:candidate:1.0")
96 .add("urn:ietf:params:netconf:capability:startup:1.0")
97 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
98 .add("urn:ietf:params:netconf:capability:interleave:1.0")
99 .add("urn:ietf:params:netconf:capability:notification:1.0")
100 .add("urn:ietf:params:netconf:capability:validate:1.0")
101 .add("urn:ietf:params:netconf:capability:validate:1.1")
102 .build();
103
104 static final List<String> DEFAULT_CAPABILITIES_1_1 = ImmutableList.<String>builder()
105 .add("urn:ietf:params:netconf:base:1.0")
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700106 .add("urn:ietf:params:netconf:base:1.1")
107 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
108 .add("urn:ietf:params:netconf:capability:candidate:1.0")
109 .add("urn:ietf:params:netconf:capability:startup:1.0")
110 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
111 .add("urn:ietf:params:netconf:capability:interleave:1.0")
112 .add("urn:ietf:params:netconf:capability:notification:1.0")
113 .add("urn:ietf:params:netconf:capability:validate:1.0")
114 .add("urn:ietf:params:netconf:capability:validate:1.1")
115 .build();
116
117
118 private static NetconfSession session1;
119 private static NetconfSession session2;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200120 private static NetconfSession session3;
121 private static NetconfSession session4;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700122 private static SshServer sshServerNetconf;
123
124 @BeforeClass
125 public static void setUp() throws Exception {
126 sshServerNetconf = SshServer.setUpDefaultServer();
127 sshServerNetconf.setPasswordAuthenticator(
128 new PasswordAuthenticator() {
129 @Override
130 public boolean authenticate(
131 String username,
132 String password,
133 ServerSession session) {
134 return TEST_USERNAME.equals(username) && TEST_PASSWORD.equals(password);
135 }
136 });
137 sshServerNetconf.setPort(PORT_NUMBER);
138 SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
139 provider.setFile(new File(TEST_SERFILE));
140 sshServerNetconf.setKeyPairProvider(provider);
141 sshServerNetconf.setSubsystemFactories(
142 Arrays.<NamedFactory<Command>>asList(new NetconfSshdTestSubsystem.Factory()));
143 sshServerNetconf.open();
144 log.info("SSH Server opened on port {}", PORT_NUMBER);
145
146 NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo(
147 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), PORT_NUMBER);
148
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200149 session1 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700150 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session1.getSessionId());
151 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("-1"));
152 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("0"));
153 assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
154
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200155 session2 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700156 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session2.getSessionId());
157 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("-1"));
158 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("0"));
159 assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200160
161 session3 = new NetconfSessionMinaImpl(deviceInfo);
162 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session3.getSessionId());
163 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("-1"));
164 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("0"));
165 assertThat(session3.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
166
167 session4 = new NetconfSessionMinaImpl(deviceInfo);
168 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session4.getSessionId());
169 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("-1"));
170 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("0"));
171 assertThat(session4.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700172 }
173
174 @AfterClass
175 public static void tearDown() throws Exception {
176 if (session1 != null) {
177 session1.close();
178 }
179 if (session2 != null) {
180 session2.close();
181 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200182 if (session3 != null) {
183 session3.close();
184 }
185 if (session4 != null) {
186 session4.close();
187 }
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700188
189 sshServerNetconf.stop();
190 }
191
192 @Test
193 public void testEditConfigRequest() {
194 log.info("Starting edit-config async");
195 assertNotNull("Incorrect sessionId", session1.getSessionId());
196 try {
197 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200198 session1.editConfig(RUNNING.toString(),
199 null, SAMPLE_REQUEST));
200 } catch (NetconfException e) {
201 e.printStackTrace();
202 fail("NETCONF edit-config test failed: " + e.getMessage());
203 }
204 log.info("Finishing edit-config async");
205 }
206
207 @Test
208 public void testEditConfigRequestWithChunkedFraming() {
209 log.info("Starting edit-config async");
210
211 assertNotNull("Incorrect sessionId", session3.getSessionId());
212 try {
213 assertTrue("NETCONF edit-config command failed",
214 session3.editConfig(RUNNING.toString(),
215 null, SAMPLE_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700216 } catch (NetconfException e) {
217 e.printStackTrace();
218 fail("NETCONF edit-config test failed: " + e.getMessage());
219 }
220 log.info("Finishing edit-config async");
221 }
222
223 @Test
224 public void testEditConfigRequestWithOnlyNewConfiguration() {
225 log.info("Starting edit-config async");
226 assertNotNull("Incorrect sessionId", session1.getSessionId());
227 try {
228 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200229 session1.editConfig(EDIT_CONFIG_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700230 } catch (NetconfException e) {
231 e.printStackTrace();
232 fail("NETCONF edit-config test failed: " + e.getMessage());
233 }
234 log.info("Finishing edit-config async");
235 }
236
237 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200238 public void testEditConfigRequestWithOnlyNewConfigurationWithChunkedFraming() {
239 log.info("Starting edit-config async");
240 assertNotNull("Incorrect sessionId", session3.getSessionId());
241 try {
242 assertTrue("NETCONF edit-config command failed",
243 session3.editConfig(EDIT_CONFIG_REQUEST));
244 } catch (NetconfException e) {
245 e.printStackTrace();
246 fail("NETCONF edit-config test failed: " + e.getMessage());
247 }
248 log.info("Finishing edit-config async");
249 }
250
251 @Test
252 public void testDeleteConfigRequestWithRunningDatastoreIdDuration() {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700253 log.info("Starting delete-config async");
254 assertNotNull("Incorrect sessionId", session1.getSessionId());
255 try {
256 assertFalse("NETCONF delete-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200257 session1.deleteConfig(RUNNING));
258 } catch (NetconfException e) {
259 e.printStackTrace();
260 fail("NETCONF delete-config test failed: " + e.getMessage());
261 }
262 log.info("Finishing delete-config async");
263 }
264
265 @Test
266 public void testDeleteConfigRequestWithRunningDatastoreIdDurationWithChunkedFraming() {
267 log.info("Starting delete-config async");
268 assertNotNull("Incorrect sessionId", session3.getSessionId());
269 try {
270 assertFalse("NETCONF delete-config command failed",
271 session3.deleteConfig(RUNNING));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700272 } catch (NetconfException e) {
273 e.printStackTrace();
274 fail("NETCONF delete-config test failed: " + e.getMessage());
275 }
276 log.info("Finishing delete-config async");
277 }
278
279 @Test
280 public void testCopyConfigRequest() {
281 log.info("Starting copy-config async");
282 assertNotNull("Incorrect sessionId", session1.getSessionId());
283 try {
284 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200285 session1.copyConfig(RUNNING.toString(),
286 "candidate"));
287 } catch (NetconfException e) {
288 e.printStackTrace();
289 fail("NETCONF edit-config test failed: " + e.getMessage());
290 }
291 log.info("Finishing copy-config async");
292 }
293
294 @Test
295 public void testCopyConfigRequestWithChunkedFraming() {
296 log.info("Starting copy-config async");
297 assertNotNull("Incorrect sessionId", session3.getSessionId());
298 try {
299 assertTrue("NETCONF copy-config command failed",
300 session3.copyConfig(RUNNING.toString(),
301 "candidate"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700302 } catch (NetconfException e) {
303 e.printStackTrace();
304 fail("NETCONF edit-config test failed: " + e.getMessage());
305 }
306 log.info("Finishing copy-config async");
307 }
308
309 @Test
310 public void testGetConfigRequest() {
311 log.info("Starting get-config async");
312 assertNotNull("Incorrect sessionId", session1.getSessionId());
313 try {
314 assertTrue("NETCONF get-config running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200315 GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700316
317 assertTrue("NETCONF get-config candidate command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200318 GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
319
320 } catch (NetconfException e) {
321 e.printStackTrace();
322 fail("NETCONF get-config test failed: " + e.getMessage());
323 }
324 log.info("Finishing get-config async");
325 }
326
327 @Test
328 public void testGetConfigRequestWithChunkedFraming() {
329 log.info("Starting get-config async");
330 assertNotNull("Incorrect sessionId", session3.getSessionId());
331 try {
332 assertTrue("NETCONF get-config running command failed. ",
333 GET_REPLY_PATTERN.matcher(session3.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
334
335 assertTrue("NETCONF get-config candidate command failed. ",
336 GET_REPLY_PATTERN.matcher(session3.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700337
338 } catch (NetconfException e) {
339 e.printStackTrace();
340 fail("NETCONF get-config test failed: " + e.getMessage());
341 }
342 log.info("Finishing get-config async");
343 }
344
345 @Test
346 public void testGetRequest() {
347 log.info("Starting get async");
348 assertNotNull("Incorrect sessionId", session1.getSessionId());
349 try {
350 assertTrue("NETCONF get running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200351 GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST, null)).matches());
352
353 } catch (NetconfException e) {
354 e.printStackTrace();
355 fail("NETCONF get test failed: " + e.getMessage());
356 }
357 log.info("Finishing get async");
358 }
359
360 @Test
361 public void testGetRequestWithChunkedFraming() {
362 log.info("Starting get async");
363 assertNotNull("Incorrect sessionId", session3.getSessionId());
364 try {
365 assertTrue("NETCONF get running command failed. ",
366 GET_REPLY_PATTERN.matcher(session3.get(SAMPLE_REQUEST, null)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700367
368 } catch (NetconfException e) {
369 e.printStackTrace();
370 fail("NETCONF get test failed: " + e.getMessage());
371 }
372 log.info("Finishing get async");
373 }
374
375 @Test
376 public void testLockRequest() {
377 log.info("Starting lock async");
378 assertNotNull("Incorrect sessionId", session1.getSessionId());
379 try {
380 assertTrue("NETCONF lock request failed", session1.lock());
381 } catch (NetconfException e) {
382 e.printStackTrace();
383 fail("NETCONF lock test failed: " + e.getMessage());
384 }
385 log.info("Finishing lock async");
386 }
387
388 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200389 public void testLockRequestWithChunkedFraming() {
390 log.info("Starting lock async");
391 assertNotNull("Incorrect sessionId", session3.getSessionId());
392 try {
393 assertTrue("NETCONF lock request failed", session3.lock());
394 } catch (NetconfException e) {
395 e.printStackTrace();
396 fail("NETCONF lock test failed: " + e.getMessage());
397 }
398 log.info("Finishing lock async");
399 }
400
401 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700402 public void testUnLockRequest() {
403 log.info("Starting unlock async");
404 assertNotNull("Incorrect sessionId", session1.getSessionId());
405 try {
406 assertTrue("NETCONF unlock request failed", session1.unlock());
407 } catch (NetconfException e) {
408 e.printStackTrace();
409 fail("NETCONF unlock test failed: " + e.getMessage());
410 }
411 log.info("Finishing unlock async");
412 }
413
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200414 @Test
415 public void testUnLockRequestWithChunkedFraming() {
416 log.info("Starting unlock async");
417 assertNotNull("Incorrect sessionId", session3.getSessionId());
418 try {
419 assertTrue("NETCONF unlock request failed", session3.unlock());
420 } catch (NetconfException e) {
421 e.printStackTrace();
422 fail("NETCONF unlock test failed: " + e.getMessage());
423 }
424 log.info("Finishing unlock async");
425 }
426
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700427
428 @Test
429 public void testConcurrentSameSessionAccess() throws InterruptedException {
430 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
431 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session1, RUNNING, "startup");
432
433 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
434 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
435
436 ExecutorService executor = Executors.newFixedThreadPool(2);
437 log.info("Starting concurrent execution of copy-config through same session");
438 executor.execute(futureCopyConfig1);
439 executor.execute(futureCopyConfig2);
440
441 int count = 0;
442 while (count < 10) {
443 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
444 executor.shutdown();
445 log.info("Finished concurrent same session execution");
446 return;
447 }
448 Thread.sleep(100L);
449 count++;
450 }
451 fail("NETCONF test failed to complete.");
452 }
453
454 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200455 public void testConcurrentSameSessionAccessWithChunkedFraming() throws InterruptedException {
456 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
457 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session3, RUNNING, "startup");
458
459 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
460 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
461
462 ExecutorService executor = Executors.newFixedThreadPool(2);
463 log.info("Starting concurrent execution of copy-config through same session");
464 executor.execute(futureCopyConfig1);
465 executor.execute(futureCopyConfig2);
466
467 int count = 0;
468 while (count < 10) {
469 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
470 executor.shutdown();
471 log.info("Finished concurrent same session execution");
472 return;
473 }
474 Thread.sleep(100L);
475 count++;
476 }
477 fail("NETCONF test failed to complete.");
478 }
479
480 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700481 public void test2SessionAccess() throws InterruptedException {
482 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
483 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session2, RUNNING, "candidate");
484
485 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
486 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
487
488 ExecutorService executor = Executors.newFixedThreadPool(2);
489 log.info("Starting concurrent execution of copy-config through 2 different sessions");
490 executor.execute(futureCopySession1);
491 executor.execute(futureCopySession2);
492
493 int count = 0;
494 while (count < 10) {
495 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
496 executor.shutdown();
497 log.info("Finished concurrent 2 session execution");
498 return;
499 }
500 Thread.sleep(100L);
501 count++;
502 }
503 fail("NETCONF test failed to complete.");
504 }
505
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200506 @Test
507 public void test2SessionAccessWithChunkedFraming() throws InterruptedException {
508 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
509 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session4, RUNNING, "candidate");
510
511 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
512 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
513
514 ExecutorService executor = Executors.newFixedThreadPool(2);
515 log.info("Starting concurrent execution of copy-config through 2 different sessions");
516 executor.execute(futureCopySession1);
517 executor.execute(futureCopySession2);
518
519 int count = 0;
520 while (count < 10) {
521 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
522 executor.shutdown();
523 log.info("Finished concurrent 2 session execution");
524 return;
525 }
526 Thread.sleep(100L);
527 count++;
528 }
529 fail("NETCONF test failed to complete.");
530 }
531
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700532
533 public static String getTestHelloReply(Optional<Long> sessionId) {
534 return getTestHelloReply(DEFAULT_CAPABILITIES, sessionId);
535 }
536
537 public static String getTestHelloReply(Collection<String> capabilities, Optional<Long> sessionId) {
538 StringBuffer sb = new StringBuffer();
539
540 sb.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
541 sb.append("<capabilities>");
542 capabilities.forEach(capability -> {
543 sb.append("<capability>").append(capability).append("</capability>");
544 });
545 sb.append("</capabilities>");
546 if (sessionId.isPresent()) {
547 sb.append("<session-id>");
548 sb.append(sessionId.get().toString());
549 sb.append("</session-id>");
550 }
551 sb.append("</hello>");
552
553 return sb.toString();
554 }
555
556 public static String getOkReply(Optional<Integer> messageId) {
557 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
558 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
559 if (messageId.isPresent()) {
560 sb.append("message-id=\"");
561 sb.append(String.valueOf(messageId.get()));
562 sb.append("\">");
563 }
564 sb.append("<ok/>");
565 sb.append("</rpc-reply>");
566 return sb.toString();
567 }
568
569 public static String getGetReply(Optional<Integer> messageId) {
570 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
571 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
572 if (messageId.isPresent()) {
573 sb.append("message-id=\"");
574 sb.append(String.valueOf(messageId.get()));
575 sb.append("\">");
576 }
577 sb.append("<data>\n");
578 sb.append(SAMPLE_REQUEST);
579 sb.append("</data>\n");
580 sb.append("</rpc-reply>");
581 return sb.toString();
582 }
583
584 public static final Pattern HELLO_REQ_PATTERN =
585 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200586 + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
587 + "( *)(<capabilities>)\\R?"
588 + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
589 + "( *)(<capability>urn:ietf:params:netconf:base:1.1</capability>)\\R?"
590 + "( *)(</capabilities>)\\R?"
591 + "(</hello>)\\R? *",
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700592 Pattern.DOTALL);
593
594 public static final Pattern EDIT_CONFIG_REQ_PATTERN =
595 Pattern.compile("(<\\?xml).*"
596 + "(<rpc message-id=\")[0-9]*(\") *(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
597 + "(<edit-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200598 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
599 + "(<" + RUNNING.toString() + "/>)|"
600 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700601 + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
602 + ".*"
603 + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
604
605
606 public static final Pattern LOCK_REQ_PATTERN =
607 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200608 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
609 + "message-id=\")[0-9]*(\">)\\R?"
610 + "(<lock>)\\R?"
611 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
612 + "(<" + RUNNING.toString() + "/>)|"
613 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
614 + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700615
616 public static final Pattern UNLOCK_REQ_PATTERN =
617 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200618 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
619 + "message-id=\")[0-9]*(\">)\\R?"
620 + "(<unlock>)\\R?"
621 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
622 + "(<" + RUNNING.toString() + "/>)|"
623 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
624 + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700625
626 public static final Pattern COPY_CONFIG_REQ_PATTERN =
627 Pattern.compile("(<\\?xml).*"
628 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
629 + "(<copy-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200630 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
631 + "(<" + RUNNING.toString() + "/>)|"
632 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
633 + "(<source>)\\R?(<config>)(("
634 + CANDIDATE.toString() + ")|("
635 + RUNNING.toString() + ")|("
636 + STARTUP.toString()
637 + "))(</config>)\\R?(</source>)\\R?"
638 + "(</copy-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700639
640 public static final Pattern GET_CONFIG_REQ_PATTERN =
641 Pattern.compile("(<\\?xml).*"
642 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
643 + "(<get-config>)\\R?" + "(<source>)\\R?((<"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200644 + CANDIDATE.toString()
645 + "/>)|(<" + RUNNING.toString()
646 + "/>)|(<" + STARTUP.toString()
647 + "/>))\\R?(</source>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700648 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
649 + "(</get-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
650
651 public static final Pattern GET_REPLY_PATTERN =
652 Pattern.compile("(<\\?xml).*"
653 + "(<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
654 + "(<data>).*(</data>)\\R?"
655 + "(</rpc-reply>)\\R?", Pattern.DOTALL);
656
657 public static final Pattern GET_REQ_PATTERN =
658 Pattern.compile("(<\\?xml).*"
659 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
660 + "(<get>)\\R?"
661 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
662 + "(</get>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
663
664 public class NCCopyConfigCallable implements Callable<Boolean> {
665 private NetconfSession session;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200666 private DatastoreId target;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700667 private String source;
668
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200669 public NCCopyConfigCallable(NetconfSession session, DatastoreId target, String source) {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700670 this.session = session;
671 this.target = target;
672 this.source = source;
673 }
674
675 @Override
676 public Boolean call() throws Exception {
677 return session.copyConfig(target, source);
678 }
679 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200680}