blob: d6cf94bcd0c73e692c581897e4a09358bd2b08c1 [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;
quan PHAM VAN32d70e52018-08-01 17:35:30 -070030import org.onlab.junit.TestUtils;
31import org.onlab.osgi.ServiceDirectory;
32import org.onlab.osgi.TestServiceDirectory;
33import org.onlab.packet.Ip4Address;
34import org.onosproject.net.driver.DriverService;
35import org.onosproject.net.driver.DriverServiceAdapter;
36import org.onosproject.netconf.DatastoreId;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070037import org.onosproject.netconf.NetconfDeviceInfo;
38import org.onosproject.netconf.NetconfException;
39import org.onosproject.netconf.NetconfSession;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070040import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43import java.io.File;
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070044import java.security.Security;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070045import java.util.Arrays;
46import java.util.Collection;
47import java.util.List;
48import java.util.Optional;
Sean Condonf096a9d2017-10-26 11:30:22 +010049import java.util.OptionalInt;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070050import java.util.concurrent.Callable;
51import java.util.concurrent.ExecutorService;
52import java.util.concurrent.Executors;
53import java.util.concurrent.FutureTask;
54import java.util.regex.Pattern;
55
56import static org.hamcrest.Matchers.containsInAnyOrder;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020057import static org.junit.Assert.assertFalse;
quan PHAM VAN32d70e52018-08-01 17:35:30 -070058import static org.junit.Assert.assertNotNull;
59import static org.junit.Assert.assertThat;
60import static org.junit.Assert.assertTrue;
61import static org.junit.Assert.fail;
Kamil Stasiak9f59f442017-05-02 11:02:24 +020062import static org.onosproject.netconf.DatastoreId.CANDIDATE;
63import static org.onosproject.netconf.DatastoreId.RUNNING;
64import static org.onosproject.netconf.DatastoreId.STARTUP;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070065
66/**
67 * Unit tests for NetconfSession.
68 * <p>
69 * Sets up an SSH Server with Apache SSHD and connects to it using 2 clients
70 * Truly verifies that the NETCONF flows are compliant with a NETCONF server.
71 */
72public class NetconfSessionMinaImplTest {
73 private static final Logger log = LoggerFactory
Yuta HIGUCHIe9761742017-09-10 15:10:19 -070074 .getLogger(NetconfSessionMinaImplTest.class);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070075
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070076 private static final String TEST_USERNAME = "netconf";
77 private static final String TEST_PASSWORD = "netconf123";
78 private static final String TEST_HOSTNAME = "127.0.0.1";
79
80 private static final String TEST_SERFILE =
81 System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") + "testkey.ser";
82
83 private static final String SAMPLE_REQUEST =
84 "<some-yang-element xmlns=\"some-namespace\">"
85 + "<some-child-element/>"
86 + "</some-yang-element>";
87
Kamil Stasiak9f59f442017-05-02 11:02:24 +020088 protected static final String EDIT_CONFIG_REQUEST =
Andrea Campanella7bbe7b12017-05-03 16:03:38 -070089 "<?xml version=\"1.0\" encoding=\"UTF-8\"?><rpc message-id=\"6\" "
90 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
91 + "<edit-config>\n"
92 + "<target><running/></target>\n"
93 + "<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
94 + "<some-yang-element xmlns=\"some-namespace\">"
95 + "<some-child-element/></some-yang-element></config>\n"
96 + "</edit-config>\n"
97 + "</rpc>]]>]]>";
98
99 static final List<String> DEFAULT_CAPABILITIES = ImmutableList.<String>builder()
100 .add("urn:ietf:params:netconf:base:1.0")
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200101 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
102 .add("urn:ietf:params:netconf:capability:candidate:1.0")
103 .add("urn:ietf:params:netconf:capability:startup:1.0")
104 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
105 .add("urn:ietf:params:netconf:capability:interleave:1.0")
106 .add("urn:ietf:params:netconf:capability:notification:1.0")
107 .add("urn:ietf:params:netconf:capability:validate:1.0")
108 .add("urn:ietf:params:netconf:capability:validate:1.1")
109 .build();
110
111 static final List<String> DEFAULT_CAPABILITIES_1_1 = ImmutableList.<String>builder()
112 .add("urn:ietf:params:netconf:base:1.0")
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700113 .add("urn:ietf:params:netconf:base:1.1")
114 .add("urn:ietf:params:netconf:capability:writable-running:1.0")
115 .add("urn:ietf:params:netconf:capability:candidate:1.0")
116 .add("urn:ietf:params:netconf:capability:startup:1.0")
117 .add("urn:ietf:params:netconf:capability:rollback-on-error:1.0")
118 .add("urn:ietf:params:netconf:capability:interleave:1.0")
119 .add("urn:ietf:params:netconf:capability:notification:1.0")
120 .add("urn:ietf:params:netconf:capability:validate:1.0")
121 .add("urn:ietf:params:netconf:capability:validate:1.1")
122 .build();
123
quan PHAM VAN32d70e52018-08-01 17:35:30 -0700124 private static final ServiceDirectory TEST_DIRECTORY =
125 new TestServiceDirectory()
126 .add(DriverService.class, new DriverServiceAdapter());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700127
128 private static NetconfSession session1;
129 private static NetconfSession session2;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200130 private static NetconfSession session3;
131 private static NetconfSession session4;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700132 private static SshServer sshServerNetconf;
133
134 @BeforeClass
135 public static void setUp() throws Exception {
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700136 Security.addProvider(new BouncyCastleProvider());
137 int portNumber = TestTools.findAvailablePort(50830);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700138 sshServerNetconf = SshServer.setUpDefaultServer();
139 sshServerNetconf.setPasswordAuthenticator(
140 new PasswordAuthenticator() {
141 @Override
142 public boolean authenticate(
143 String username,
144 String password,
145 ServerSession session) {
146 return TEST_USERNAME.equals(username) && TEST_PASSWORD.equals(password);
147 }
148 });
quan PHAM VAN32d70e52018-08-01 17:35:30 -0700149
150 TestUtils.setField(NetconfSessionMinaImpl.class, "directory", TEST_DIRECTORY);
151
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700152 sshServerNetconf.setPort(portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700153 SimpleGeneratorHostKeyProvider provider = new SimpleGeneratorHostKeyProvider();
154 provider.setFile(new File(TEST_SERFILE));
155 sshServerNetconf.setKeyPairProvider(provider);
156 sshServerNetconf.setSubsystemFactories(
157 Arrays.<NamedFactory<Command>>asList(new NetconfSshdTestSubsystem.Factory()));
158 sshServerNetconf.open();
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700159 log.info("SSH Server opened on port {}", portNumber);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700160
161 NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo(
Yuta HIGUCHIe9761742017-09-10 15:10:19 -0700162 TEST_USERNAME, TEST_PASSWORD, Ip4Address.valueOf(TEST_HOSTNAME), portNumber);
Sean Condonf096a9d2017-10-26 11:30:22 +0100163 deviceInfo.setConnectTimeoutSec(OptionalInt.of(30));
164 deviceInfo.setReplyTimeoutSec(OptionalInt.of(30));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700165
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200166 session1 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700167 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session1.getSessionId());
168 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("-1"));
169 assertTrue("Incorrect sessionId", !session1.getSessionId().equalsIgnoreCase("0"));
170 assertThat(session1.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
171
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200172 session2 = new NetconfSessionMinaImpl(deviceInfo, ImmutableList.of("urn:ietf:params:netconf:base:1.0"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700173 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session2.getSessionId());
174 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("-1"));
175 assertTrue("Incorrect sessionId", !session2.getSessionId().equalsIgnoreCase("0"));
176 assertThat(session2.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES.toArray()));
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200177
178 session3 = new NetconfSessionMinaImpl(deviceInfo);
179 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session3.getSessionId());
180 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("-1"));
181 assertTrue("Incorrect sessionId", !session3.getSessionId().equalsIgnoreCase("0"));
182 assertThat(session3.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
183
184 session4 = new NetconfSessionMinaImpl(deviceInfo);
185 log.info("Started NETCONF Session {} with test SSHD server in Unit Test", session4.getSessionId());
186 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("-1"));
187 assertTrue("Incorrect sessionId", !session4.getSessionId().equalsIgnoreCase("0"));
188 assertThat(session4.getDeviceCapabilitiesSet(), containsInAnyOrder(DEFAULT_CAPABILITIES_1_1.toArray()));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700189 }
190
191 @AfterClass
192 public static void tearDown() throws Exception {
193 if (session1 != null) {
194 session1.close();
195 }
196 if (session2 != null) {
197 session2.close();
198 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200199 if (session3 != null) {
200 session3.close();
201 }
202 if (session4 != null) {
203 session4.close();
204 }
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700205
quan PHAM VAN32d70e52018-08-01 17:35:30 -0700206 TestUtils.setField(NetconfSessionMinaImpl.class, "directory", null);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700207 sshServerNetconf.stop();
208 }
209
210 @Test
211 public void testEditConfigRequest() {
212 log.info("Starting edit-config async");
213 assertNotNull("Incorrect sessionId", session1.getSessionId());
214 try {
215 assertTrue("NETCONF edit-config command failed",
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700216 session1.editConfig(RUNNING,
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200217 null, SAMPLE_REQUEST));
218 } catch (NetconfException e) {
219 e.printStackTrace();
220 fail("NETCONF edit-config test failed: " + e.getMessage());
221 }
222 log.info("Finishing edit-config async");
223 }
224
225 @Test
226 public void testEditConfigRequestWithChunkedFraming() {
227 log.info("Starting edit-config async");
228
229 assertNotNull("Incorrect sessionId", session3.getSessionId());
230 try {
231 assertTrue("NETCONF edit-config command failed",
Yuta HIGUCHIdd7c3f82017-09-03 14:18:01 -0700232 session3.editConfig(RUNNING,
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200233 null, SAMPLE_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -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 testEditConfigRequestWithOnlyNewConfiguration() {
243 log.info("Starting edit-config async");
244 assertNotNull("Incorrect sessionId", session1.getSessionId());
245 try {
246 assertTrue("NETCONF edit-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200247 session1.editConfig(EDIT_CONFIG_REQUEST));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700248 } catch (NetconfException e) {
249 e.printStackTrace();
250 fail("NETCONF edit-config test failed: " + e.getMessage());
251 }
252 log.info("Finishing edit-config async");
253 }
254
255 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200256 public void testEditConfigRequestWithOnlyNewConfigurationWithChunkedFraming() {
257 log.info("Starting edit-config async");
258 assertNotNull("Incorrect sessionId", session3.getSessionId());
259 try {
260 assertTrue("NETCONF edit-config command failed",
261 session3.editConfig(EDIT_CONFIG_REQUEST));
262 } catch (NetconfException e) {
263 e.printStackTrace();
264 fail("NETCONF edit-config test failed: " + e.getMessage());
265 }
266 log.info("Finishing edit-config async");
267 }
268
269 @Test
270 public void testDeleteConfigRequestWithRunningDatastoreIdDuration() {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700271 log.info("Starting delete-config async");
272 assertNotNull("Incorrect sessionId", session1.getSessionId());
273 try {
274 assertFalse("NETCONF delete-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200275 session1.deleteConfig(RUNNING));
276 } catch (NetconfException e) {
277 e.printStackTrace();
278 fail("NETCONF delete-config test failed: " + e.getMessage());
279 }
280 log.info("Finishing delete-config async");
281 }
282
283 @Test
284 public void testDeleteConfigRequestWithRunningDatastoreIdDurationWithChunkedFraming() {
285 log.info("Starting delete-config async");
286 assertNotNull("Incorrect sessionId", session3.getSessionId());
287 try {
288 assertFalse("NETCONF delete-config command failed",
289 session3.deleteConfig(RUNNING));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700290 } catch (NetconfException e) {
291 e.printStackTrace();
292 fail("NETCONF delete-config test failed: " + e.getMessage());
293 }
294 log.info("Finishing delete-config async");
295 }
296
297 @Test
298 public void testCopyConfigRequest() {
299 log.info("Starting copy-config async");
300 assertNotNull("Incorrect sessionId", session1.getSessionId());
301 try {
302 assertTrue("NETCONF copy-config command failed",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200303 session1.copyConfig(RUNNING.toString(),
304 "candidate"));
305 } 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 testCopyConfigRequestWithChunkedFraming() {
314 log.info("Starting copy-config async");
315 assertNotNull("Incorrect sessionId", session3.getSessionId());
316 try {
317 assertTrue("NETCONF copy-config command failed",
318 session3.copyConfig(RUNNING.toString(),
319 "candidate"));
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700320 } catch (NetconfException e) {
321 e.printStackTrace();
322 fail("NETCONF edit-config test failed: " + e.getMessage());
323 }
324 log.info("Finishing copy-config async");
325 }
326
327 @Test
328 public void testGetConfigRequest() {
329 log.info("Starting get-config async");
330 assertNotNull("Incorrect sessionId", session1.getSessionId());
331 try {
332 assertTrue("NETCONF get-config running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200333 GET_REPLY_PATTERN.matcher(session1.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700334
335 assertTrue("NETCONF get-config candidate command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200336 GET_REPLY_PATTERN.matcher(session1.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
337
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 testGetConfigRequestWithChunkedFraming() {
347 log.info("Starting get-config async");
348 assertNotNull("Incorrect sessionId", session3.getSessionId());
349 try {
350 assertTrue("NETCONF get-config running command failed. ",
351 GET_REPLY_PATTERN.matcher(session3.getConfig(RUNNING, SAMPLE_REQUEST)).matches());
352
353 assertTrue("NETCONF get-config candidate command failed. ",
354 GET_REPLY_PATTERN.matcher(session3.getConfig(CANDIDATE, SAMPLE_REQUEST)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700355
356 } catch (NetconfException e) {
357 e.printStackTrace();
358 fail("NETCONF get-config test failed: " + e.getMessage());
359 }
360 log.info("Finishing get-config async");
361 }
362
363 @Test
364 public void testGetRequest() {
365 log.info("Starting get async");
366 assertNotNull("Incorrect sessionId", session1.getSessionId());
367 try {
368 assertTrue("NETCONF get running command failed. ",
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200369 GET_REPLY_PATTERN.matcher(session1.get(SAMPLE_REQUEST, null)).matches());
370
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 testGetRequestWithChunkedFraming() {
380 log.info("Starting get async");
381 assertNotNull("Incorrect sessionId", session3.getSessionId());
382 try {
383 assertTrue("NETCONF get running command failed. ",
384 GET_REPLY_PATTERN.matcher(session3.get(SAMPLE_REQUEST, null)).matches());
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700385
386 } catch (NetconfException e) {
387 e.printStackTrace();
388 fail("NETCONF get test failed: " + e.getMessage());
389 }
390 log.info("Finishing get async");
391 }
392
393 @Test
394 public void testLockRequest() {
395 log.info("Starting lock async");
396 assertNotNull("Incorrect sessionId", session1.getSessionId());
397 try {
398 assertTrue("NETCONF lock request failed", session1.lock());
399 } catch (NetconfException e) {
400 e.printStackTrace();
401 fail("NETCONF lock test failed: " + e.getMessage());
402 }
403 log.info("Finishing lock async");
404 }
405
406 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200407 public void testLockRequestWithChunkedFraming() {
408 log.info("Starting lock async");
409 assertNotNull("Incorrect sessionId", session3.getSessionId());
410 try {
411 assertTrue("NETCONF lock request failed", session3.lock());
412 } catch (NetconfException e) {
413 e.printStackTrace();
414 fail("NETCONF lock test failed: " + e.getMessage());
415 }
416 log.info("Finishing lock async");
417 }
418
419 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700420 public void testUnLockRequest() {
421 log.info("Starting unlock async");
422 assertNotNull("Incorrect sessionId", session1.getSessionId());
423 try {
424 assertTrue("NETCONF unlock request failed", session1.unlock());
425 } catch (NetconfException e) {
426 e.printStackTrace();
427 fail("NETCONF unlock test failed: " + e.getMessage());
428 }
429 log.info("Finishing unlock async");
430 }
431
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200432 @Test
433 public void testUnLockRequestWithChunkedFraming() {
434 log.info("Starting unlock async");
435 assertNotNull("Incorrect sessionId", session3.getSessionId());
436 try {
437 assertTrue("NETCONF unlock request failed", session3.unlock());
438 } catch (NetconfException e) {
439 e.printStackTrace();
440 fail("NETCONF unlock test failed: " + e.getMessage());
441 }
442 log.info("Finishing unlock async");
443 }
444
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700445
446 @Test
447 public void testConcurrentSameSessionAccess() throws InterruptedException {
448 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
449 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session1, RUNNING, "startup");
450
451 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
452 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
453
454 ExecutorService executor = Executors.newFixedThreadPool(2);
455 log.info("Starting concurrent execution of copy-config through same session");
456 executor.execute(futureCopyConfig1);
457 executor.execute(futureCopyConfig2);
458
459 int count = 0;
460 while (count < 10) {
461 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
462 executor.shutdown();
463 log.info("Finished concurrent same session execution");
464 return;
465 }
466 Thread.sleep(100L);
467 count++;
468 }
469 fail("NETCONF test failed to complete.");
470 }
471
472 @Test
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200473 public void testConcurrentSameSessionAccessWithChunkedFraming() throws InterruptedException {
474 NCCopyConfigCallable testCopyConfig1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
475 NCCopyConfigCallable testCopyConfig2 = new NCCopyConfigCallable(session3, RUNNING, "startup");
476
477 FutureTask<Boolean> futureCopyConfig1 = new FutureTask<>(testCopyConfig1);
478 FutureTask<Boolean> futureCopyConfig2 = new FutureTask<>(testCopyConfig2);
479
480 ExecutorService executor = Executors.newFixedThreadPool(2);
481 log.info("Starting concurrent execution of copy-config through same session");
482 executor.execute(futureCopyConfig1);
483 executor.execute(futureCopyConfig2);
484
485 int count = 0;
486 while (count < 10) {
487 if (futureCopyConfig1.isDone() && futureCopyConfig2.isDone()) {
488 executor.shutdown();
489 log.info("Finished concurrent same session execution");
490 return;
491 }
492 Thread.sleep(100L);
493 count++;
494 }
495 fail("NETCONF test failed to complete.");
496 }
497
498 @Test
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700499 public void test2SessionAccess() throws InterruptedException {
500 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session1, RUNNING, "candidate");
501 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session2, RUNNING, "candidate");
502
503 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
504 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
505
506 ExecutorService executor = Executors.newFixedThreadPool(2);
507 log.info("Starting concurrent execution of copy-config through 2 different sessions");
508 executor.execute(futureCopySession1);
509 executor.execute(futureCopySession2);
510
511 int count = 0;
512 while (count < 10) {
513 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
514 executor.shutdown();
515 log.info("Finished concurrent 2 session execution");
516 return;
517 }
518 Thread.sleep(100L);
519 count++;
520 }
521 fail("NETCONF test failed to complete.");
522 }
523
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200524 @Test
525 public void test2SessionAccessWithChunkedFraming() throws InterruptedException {
526 NCCopyConfigCallable testCopySession1 = new NCCopyConfigCallable(session3, RUNNING, "candidate");
527 NCCopyConfigCallable testCopySession2 = new NCCopyConfigCallable(session4, RUNNING, "candidate");
528
529 FutureTask<Boolean> futureCopySession1 = new FutureTask<>(testCopySession1);
530 FutureTask<Boolean> futureCopySession2 = new FutureTask<>(testCopySession2);
531
532 ExecutorService executor = Executors.newFixedThreadPool(2);
533 log.info("Starting concurrent execution of copy-config through 2 different sessions");
534 executor.execute(futureCopySession1);
535 executor.execute(futureCopySession2);
536
537 int count = 0;
538 while (count < 10) {
539 if (futureCopySession1.isDone() && futureCopySession2.isDone()) {
540 executor.shutdown();
541 log.info("Finished concurrent 2 session execution");
542 return;
543 }
544 Thread.sleep(100L);
545 count++;
546 }
547 fail("NETCONF test failed to complete.");
548 }
549
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700550
551 public static String getTestHelloReply(Optional<Long> sessionId) {
552 return getTestHelloReply(DEFAULT_CAPABILITIES, sessionId);
553 }
554
555 public static String getTestHelloReply(Collection<String> capabilities, Optional<Long> sessionId) {
556 StringBuffer sb = new StringBuffer();
557
558 sb.append("<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">");
559 sb.append("<capabilities>");
560 capabilities.forEach(capability -> {
561 sb.append("<capability>").append(capability).append("</capability>");
562 });
563 sb.append("</capabilities>");
564 if (sessionId.isPresent()) {
565 sb.append("<session-id>");
566 sb.append(sessionId.get().toString());
567 sb.append("</session-id>");
568 }
569 sb.append("</hello>");
570
571 return sb.toString();
572 }
573
574 public static String getOkReply(Optional<Integer> messageId) {
575 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
576 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
577 if (messageId.isPresent()) {
578 sb.append("message-id=\"");
579 sb.append(String.valueOf(messageId.get()));
580 sb.append("\">");
581 }
582 sb.append("<ok/>");
583 sb.append("</rpc-reply>");
584 return sb.toString();
585 }
586
587 public static String getGetReply(Optional<Integer> messageId) {
588 StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
589 sb.append("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" ");
590 if (messageId.isPresent()) {
591 sb.append("message-id=\"");
592 sb.append(String.valueOf(messageId.get()));
593 sb.append("\">");
594 }
595 sb.append("<data>\n");
596 sb.append(SAMPLE_REQUEST);
597 sb.append("</data>\n");
598 sb.append("</rpc-reply>");
599 return sb.toString();
600 }
601
602 public static final Pattern HELLO_REQ_PATTERN =
603 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200604 + "(<hello xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
605 + "( *)(<capabilities>)\\R?"
606 + "( *)(<capability>urn:ietf:params:netconf:base:1.0</capability>)\\R?"
607 + "( *)(<capability>urn:ietf:params:netconf:base:1.1</capability>)\\R?"
608 + "( *)(</capabilities>)\\R?"
609 + "(</hello>)\\R? *",
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700610 Pattern.DOTALL);
611
612 public static final Pattern EDIT_CONFIG_REQ_PATTERN =
613 Pattern.compile("(<\\?xml).*"
614 + "(<rpc message-id=\")[0-9]*(\") *(xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
615 + "(<edit-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200616 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
617 + "(<" + RUNNING.toString() + "/>)|"
618 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700619 + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
620 + ".*"
621 + "(</config>)\\R?(</edit-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
622
623
624 public static final Pattern LOCK_REQ_PATTERN =
625 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200626 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
627 + "message-id=\")[0-9]*(\">)\\R?"
628 + "(<lock>)\\R?"
629 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
630 + "(<" + RUNNING.toString() + "/>)|"
631 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
632 + "(</lock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700633
634 public static final Pattern UNLOCK_REQ_PATTERN =
635 Pattern.compile("(<\\?xml).*"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200636 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" "
637 + "message-id=\")[0-9]*(\">)\\R?"
638 + "(<unlock>)\\R?"
639 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
640 + "(<" + RUNNING.toString() + "/>)|"
641 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
642 + "(</unlock>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700643
644 public static final Pattern COPY_CONFIG_REQ_PATTERN =
645 Pattern.compile("(<\\?xml).*"
646 + "(<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
647 + "(<copy-config>)\\R?"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200648 + "(<target>\\R?((<" + CANDIDATE.toString() + "/>)|"
649 + "(<" + RUNNING.toString() + "/>)|"
650 + "(<" + STARTUP.toString() + "/>))\\R?</target>)\\R?"
651 + "(<source>)\\R?(<config>)(("
652 + CANDIDATE.toString() + ")|("
653 + RUNNING.toString() + ")|("
654 + STARTUP.toString()
655 + "))(</config>)\\R?(</source>)\\R?"
656 + "(</copy-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700657
658 public static final Pattern GET_CONFIG_REQ_PATTERN =
659 Pattern.compile("(<\\?xml).*"
660 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
661 + "(<get-config>)\\R?" + "(<source>)\\R?((<"
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200662 + CANDIDATE.toString()
663 + "/>)|(<" + RUNNING.toString()
664 + "/>)|(<" + STARTUP.toString()
665 + "/>))\\R?(</source>)\\R?"
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700666 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
667 + "(</get-config>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
668
669 public static final Pattern GET_REPLY_PATTERN =
670 Pattern.compile("(<\\?xml).*"
671 + "(<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\" message-id=\")[0-9]*(\">)\\R?"
672 + "(<data>).*(</data>)\\R?"
673 + "(</rpc-reply>)\\R?", Pattern.DOTALL);
674
675 public static final Pattern GET_REQ_PATTERN =
676 Pattern.compile("(<\\?xml).*"
677 + "(<rpc message-id=\")[0-9]*(\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
678 + "(<get>)\\R?"
679 + "(<filter type=\"subtree\">).*(</filter>)\\R?"
680 + "(</get>)\\R?(</rpc>)\\R?", Pattern.DOTALL);
681
682 public class NCCopyConfigCallable implements Callable<Boolean> {
683 private NetconfSession session;
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200684 private DatastoreId target;
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700685 private String source;
686
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200687 public NCCopyConfigCallable(NetconfSession session, DatastoreId target, String source) {
Andrea Campanella7bbe7b12017-05-03 16:03:38 -0700688 this.session = session;
689 this.target = target;
690 this.source = source;
691 }
692
693 @Override
694 public Boolean call() throws Exception {
695 return session.copyConfig(target, source);
696 }
697 }
Kamil Stasiak9f59f442017-05-02 11:02:24 +0200698}