]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/mgmt_tests/test_yang_mgmt.py
Merge pull request #13455 from sri-mohan1/srib-ldpd
[mirror_frr.git] / tests / topotests / mgmt_tests / test_yang_mgmt.py
1 #!/usr/bin/python
2
3 #
4 # Copyright (c) 2021 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation,
6 # Inc. ("NetDEF") in this file.
7 #
8 # Permission to use, copy, modify, and/or distribute this software
9 # for any purpose with or without fee is hereby granted, provided
10 # that the above copyright notice and this permission notice appear
11 # in all copies.
12 #
13 # THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
14 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
16 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
17 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
19 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 # OF THIS SOFTWARE.
21 #
22 """
23
24 1. Verify mgmt commit check.
25 2. Verify mgmt commit apply.
26 3. Verify mgmt commit abort.
27 4. Verify mgmt delete config.
28 5. Kill mgmtd - verify that static routes are intact.
29 6. Kill mgmtd - verify that watch frr restarts.
30 7. Show and CLI - Execute all the newly introduced commands of mgmtd.
31 8. Verify mgmt rollback functionality.
32
33 """
34 import sys
35 import time
36 import os
37 import pytest
38 import platform
39
40 # Save the Current Working Directory to find configuration files.
41 CWD = os.path.dirname(os.path.realpath(__file__))
42 sys.path.append(os.path.join(CWD, "../"))
43 sys.path.append(os.path.join(CWD, "../lib/"))
44
45 # pylint: disable=C0413
46 # Import topogen and topotest helpers
47 from lib.topogen import Topogen, get_topogen
48 from lib.topotest import version_cmp
49
50 # Import topoJson from lib, to create topology and initial configuration
51 from lib.common_config import (
52 start_topology,
53 write_test_header,
54 write_test_footer,
55 reset_config_on_routers,
56 verify_rib,
57 create_static_routes,
58 check_address_types,
59 step,
60 shutdown_bringup_interface,
61 stop_router,
62 start_router,
63 apply_raw_config,
64 kill_router_daemons,
65 start_router_daemons,
66 )
67 from lib.topolog import logger
68 from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
69 from lib.topojson import build_config_from_json
70
71 pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
72
73 # Global variables
74 ADDR_TYPES = check_address_types()
75 NETWORK = {"ipv4": ["11.0.20.1/32", "11.0.20.2/32"], "ipv6": ["2::1/128", "2::2/128"]}
76 NETWORK2 = {"ipv4": "11.0.20.1/32", "ipv6": "2::1/128"}
77 PREFIX1 = {"ipv4": "110.0.20.1/32", "ipv6": "20::1/128"}
78
79
80 def setup_module(mod):
81 """
82 Sets up the pytest environment.
83
84 * `mod`: module name
85 """
86
87 testsuite_run_time = time.asctime(time.localtime(time.time()))
88 logger.info("Testsuite start time: {}".format(testsuite_run_time))
89 logger.info("=" * 40)
90
91 logger.info("Running setup_module to create topology")
92
93 # This function initiates the topology build with Topogen...
94 json_file = "{}/yang_mgmt.json".format(CWD)
95 tgen = Topogen(json_file, mod.__name__)
96 global topo
97 topo = tgen.json_topo
98 # ... and here it calls Mininet initialization functions.
99
100 # Starting topology, create tmp files which are loaded to routers
101 # to start deamons and then start routers
102 start_topology(tgen)
103
104 # Creating configuration from JSON
105 build_config_from_json(tgen, topo)
106
107 if version_cmp(platform.release(), "4.19") < 0:
108 error_msg = (
109 'These tests will not run. (have kernel "{}", '
110 "requires kernel >= 4.19)".format(platform.release())
111 )
112 pytest.skip(error_msg)
113
114 # Don't run this test if we have any failure.
115 if tgen.routers_have_failure():
116 pytest.skip(tgen.errors)
117
118 logger.info("Running setup_module() done")
119
120
121 def teardown_module(mod):
122 """
123 Teardown the pytest environment.
124
125 * `mod`: module name
126 """
127
128 logger.info("Running teardown_module to delete topology: %s", mod)
129
130 tgen = get_topogen()
131
132 # Stop toplogy and Remove tmp files
133 tgen.stop_topology()
134
135 logger.info(
136 "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
137 )
138 logger.info("=" * 40)
139
140
141 def populate_nh():
142 """
143 Populate nexthops.
144 """
145
146 next_hop_ip = {
147 "nh1": {
148 "ipv4": topo["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
149 "ipv6": topo["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
150 },
151 "nh2": {
152 "ipv4": topo["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
153 "ipv6": topo["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
154 },
155 }
156 return next_hop_ip
157
158
159 #####################################################
160 #
161 # Testcases
162 #
163 #####################################################
164
165
166 def test_mgmt_commit_check(request):
167 """
168 Verify mgmt commit check.
169
170 """
171 tc_name = request.node.name
172 write_test_header(tc_name)
173 tgen = get_topogen()
174 # Don't run this test if we have any failure.
175 if tgen.routers_have_failure():
176 pytest.skip(tgen.errors)
177
178 reset_config_on_routers(tgen)
179
180 step("Mgmt Commit check")
181 raw_config = {
182 "r1": {
183 "raw_config": [
184 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.1.2/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/bh-type unspec",
185 "mgmt commit check",
186 ]
187 }
188 }
189
190 result = apply_raw_config(tgen, raw_config)
191 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
192
193 step("Mgmt Commit check")
194 raw_config = {
195 "r1": {
196 "raw_config": [
197 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.1.2/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/bh-type unspec",
198 "mgmt commit check",
199 ]
200 }
201 }
202
203 result = apply_raw_config(tgen, raw_config)
204 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
205
206 step("verify that the route is not configured, as commit apply not done.")
207
208 dut = "r1"
209 protocol = "static"
210 input_dict_4 = {
211 "r2": {
212 "static_routes": [
213 {
214 "network": "1192.1.1.2/32",
215 "next_hop": "Null0",
216 }
217 ]
218 }
219 }
220 result = verify_rib(
221 tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
222 )
223 assert (
224 result is not True
225 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
226
227 write_test_footer(tc_name)
228
229
230 def test_mgmt_commit_apply(request):
231 """
232 Verify mgmt commit apply.
233
234 """
235 tc_name = request.node.name
236 write_test_header(tc_name)
237 tgen = get_topogen()
238 # Don't run this test if we have any failure.
239 if tgen.routers_have_failure():
240 pytest.skip(tgen.errors)
241
242 reset_config_on_routers(tgen)
243
244 step("Mgmt Commit apply with Valid Configuration")
245 raw_config = {
246 "r1": {
247 "raw_config": [
248 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.1.20/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/vrf default",
249 "mgmt commit apply",
250 ]
251 }
252 }
253
254 result = apply_raw_config(tgen, raw_config)
255 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
256
257 step("Mgmt Commit apply with Invalid Configuration")
258 raw_config = {
259 "r1": {
260 "raw_config": [
261 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.1.20/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/vrf default",
262 "mgmt commit apply",
263 ]
264 }
265 }
266
267 result = apply_raw_config(tgen, raw_config)
268 assert result is not True, "Testcase {} : Failed Error: {}".format(tc_name, result)
269
270 step("verify that the route is configured")
271
272 dut = "r1"
273 protocol = "static"
274 input_dict_4 = {"r2": {"static_routes": [{"network": "192.1.1.20/32"}]}}
275 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
276 assert (
277 result is True
278 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
279
280 write_test_footer(tc_name)
281
282
283 def test_mgmt_commit_abort(request):
284 """
285 Verify mgmt commit abort.
286
287 """
288 tc_name = request.node.name
289 write_test_header(tc_name)
290 tgen = get_topogen()
291 # Don't run this test if we have any failure.
292 if tgen.routers_have_failure():
293 pytest.skip(tgen.errors)
294
295 reset_config_on_routers(tgen)
296
297 step("Mgmt Commit abort")
298 raw_config = {
299 "r1": {
300 "raw_config": [
301 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.1.3/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/vrf default",
302 "mgmt commit abort",
303 ]
304 }
305 }
306
307 result = apply_raw_config(tgen, raw_config)
308 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
309
310 step("verify that the route is not configured")
311
312 dut = "r1"
313 protocol = "static"
314 input_dict_4 = {
315 "r2": {
316 "static_routes": [
317 {
318 "network": "192.1.1.3/32",
319 "next_hop": "Null0",
320 }
321 ]
322 }
323 }
324 result = verify_rib(
325 tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
326 )
327 assert (
328 result is not True
329 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
330
331 write_test_footer(tc_name)
332
333
334 def test_mgmt_delete_config(request):
335 """
336 Verify mgmt delete config.
337
338 """
339 tc_name = request.node.name
340 write_test_header(tc_name)
341 tgen = get_topogen()
342 # Don't run this test if we have any failure.
343 if tgen.routers_have_failure():
344 pytest.skip(tgen.errors)
345
346 reset_config_on_routers(tgen)
347
348 step("Mgmt - Configure a static route using commit apply")
349
350 raw_config = {
351 "r1": {
352 "raw_config": [
353 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.168.1.3/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/vrf default",
354 "mgmt commit apply",
355 ]
356 }
357 }
358
359 result = apply_raw_config(tgen, raw_config)
360 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
361
362 step("Verify that the route is added to RIB")
363 dut = "r1"
364 protocol = "static"
365 input_dict_4 = {
366 "r2": {
367 "static_routes": [
368 {
369 "network": "192.168.1.3/32",
370 "next_hop": "Null0",
371 }
372 ]
373 }
374 }
375 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
376 assert (
377 result is True
378 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
379
380 step("Mgmt delete config")
381 raw_config = {
382 "r1": {
383 "raw_config": [
384 "mgmt delete-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.168.1.3/32'][afi-safi='frr-routing:ipv4-unicast']",
385 "mgmt commit apply",
386 ]
387 }
388 }
389
390 result = apply_raw_config(tgen, raw_config)
391 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
392
393 step("Verify that the route is deleted from RIB")
394 result = verify_rib(
395 tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
396 )
397 assert (
398 result is not True
399 ), "Testcase {} : Failed" "Error: Routes is still present in RIB".format(tc_name)
400
401 write_test_footer(tc_name)
402
403
404 def test_mgmt_chaos_stop_start_frr(request):
405 """
406 Kill mgmtd - verify that watch frr restarts.
407
408 """
409 tc_name = request.node.name
410 write_test_header(tc_name)
411 tgen = get_topogen()
412 # Don't run this test if we have any failure.
413 if tgen.routers_have_failure():
414 pytest.skip(tgen.errors)
415
416 reset_config_on_routers(tgen)
417 next_hop_ip = populate_nh()
418
419 step("Configure Static route with next hop null 0")
420
421 raw_config = {
422 "r1": {
423 "raw_config": [
424 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.11.200/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/bh-type unspec",
425 "mgmt commit apply",
426 ]
427 }
428 }
429
430 result = apply_raw_config(tgen, raw_config)
431 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
432
433 step("verify that the route is configured and present in the zebra")
434
435 dut = "r1"
436 protocol = "static"
437 input_dict_4 = {"r2": {"static_routes": [{"network": "192.1.11.200/32"}]}}
438 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
439 assert (
440 result is True
441 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
442
443 step("Restart frr")
444 stop_router(tgen, "r1")
445 start_router(tgen, "r1")
446 step("Verify routes are intact in zebra.")
447 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
448 assert (
449 result is True
450 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
451
452 step("delete the configured route and ")
453 raw_config = {
454 "r1": {
455 "raw_config": [
456 "mgmt delete-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.11.200/32'][afi-safi='frr-routing:ipv4-unicast']",
457 "mgmt commit apply",
458 ]
459 }
460 }
461
462 result = apply_raw_config(tgen, raw_config)
463 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
464
465 step("verify that the route is deleted and deleted from zebra")
466
467 dut = "r1"
468 protocol = "static"
469 input_dict_4 = {"r1": {"static_routes": [{"network": "192.1.11.200/32"}]}}
470 result = verify_rib(
471 tgen, "ipv4", dut, input_dict_4, protocol=protocol, expected=False
472 )
473 assert (
474 result is not True
475 ), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name)
476
477 write_test_footer(tc_name)
478
479
480 def test_mgmt_chaos_kill_daemon(request):
481 """
482 Kill mgmtd - verify that static routes are intact
483
484 """
485 tc_name = request.node.name
486 write_test_header(tc_name)
487 tgen = get_topogen()
488 # Don't run this test if we have any failure.
489 if tgen.routers_have_failure():
490 pytest.skip(tgen.errors)
491
492 reset_config_on_routers(tgen)
493 next_hop_ip = populate_nh()
494
495 step("Configure Static route with next hop null 0")
496
497 raw_config = {
498 "r1": {
499 "raw_config": [
500 "mgmt set-config /frr-routing:routing/control-plane-protocols/control-plane-protocol[type='frr-staticd:staticd'][name='staticd'][vrf='default']/frr-staticd:staticd/route-list[prefix='192.1.11.200/32'][afi-safi='frr-routing:ipv4-unicast']/path-list[table-id='0'][distance='1']/frr-nexthops/nexthop[nh-type='blackhole'][vrf='default'][gateway=''][interface='(null)']/bh-type unspec",
501 "mgmt commit apply",
502 ]
503 }
504 }
505
506 result = apply_raw_config(tgen, raw_config)
507 assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
508
509 step("verify that the route is configured and present in the zebra")
510
511 dut = "r1"
512 protocol = "static"
513 input_dict_4 = {"r2": {"static_routes": [{"network": "192.1.11.200/32"}]}}
514 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
515 assert (
516 result is True
517 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
518
519 step("Kill static daemon on R2.")
520 kill_router_daemons(tgen, "r1", ["staticd"])
521
522 step("Bring up staticd daemon on R2.")
523 start_router_daemons(tgen, "r1", ["staticd"])
524
525 step("Verify routes are intact in zebra.")
526 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
527 assert (
528 result is True
529 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
530
531 step("Kill mgmt daemon on R2.")
532 kill_router_daemons(tgen, "r1", ["mgmtd"])
533
534 step("Bring up zebra daemon on R2.")
535 start_router_daemons(tgen, "r1", ["mgmtd"])
536
537 step("Verify routes are intact in zebra.")
538 result = verify_rib(tgen, "ipv4", dut, input_dict_4, protocol=protocol)
539 assert (
540 result is True
541 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name)
542
543 write_test_footer(tc_name)
544
545
546 if __name__ == "__main__":
547 args = ["-s"] + sys.argv[1:]
548 sys.exit(pytest.main(args))