4 # Copyright (c) 2021 by VMware, Inc. ("VMware")
5 # Used Copyright (c) 2018 by Network Device Education Foundation,
6 # Inc. ("NetDEF") in this file.
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
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
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.
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/"))
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
50 # Import topoJson from lib, to create topology and initial configuration
51 from lib
.common_config
import (
55 reset_config_on_routers
,
60 shutdown_bringup_interface
,
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
71 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.staticd
]
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"}
80 def setup_module(mod
):
82 Sets up the pytest environment.
87 testsuite_run_time
= time
.asctime(time
.localtime(time
.time()))
88 logger
.info("Testsuite start time: {}".format(testsuite_run_time
))
91 logger
.info("Running setup_module to create topology")
93 # This function initiates the topology build with Topogen...
94 json_file
= "{}/yang_mgmt.json".format(CWD
)
95 tgen
= Topogen(json_file
, mod
.__name
__)
98 # ... and here it calls Mininet initialization functions.
100 # Starting topology, create tmp files which are loaded to routers
101 # to start deamons and then start routers
104 # Creating configuration from JSON
105 build_config_from_json(tgen
, topo
)
107 if version_cmp(platform
.release(), "4.19") < 0:
109 'These tests will not run. (have kernel "{}", '
110 "requires kernel >= 4.19)".format(platform
.release())
112 pytest
.skip(error_msg
)
114 # Don't run this test if we have any failure.
115 if tgen
.routers_have_failure():
116 pytest
.skip(tgen
.errors
)
118 logger
.info("Running setup_module() done")
121 def teardown_module(mod
):
123 Teardown the pytest environment.
128 logger
.info("Running teardown_module to delete topology: %s", mod
)
132 # Stop toplogy and Remove tmp files
136 "Testsuite end time: {}".format(time
.asctime(time
.localtime(time
.time())))
138 logger
.info("=" * 40)
148 "ipv4": topo
["routers"]["r1"]["links"]["r2-link0"]["ipv4"].split("/")[0],
149 "ipv6": topo
["routers"]["r1"]["links"]["r2-link0"]["ipv6"].split("/")[0],
152 "ipv4": topo
["routers"]["r1"]["links"]["r2-link1"]["ipv4"].split("/")[0],
153 "ipv6": topo
["routers"]["r1"]["links"]["r2-link1"]["ipv6"].split("/")[0],
159 #####################################################
163 #####################################################
166 def test_mgmt_commit_check(request
):
168 Verify mgmt commit check.
171 tc_name
= request
.node
.name
172 write_test_header(tc_name
)
174 # Don't run this test if we have any failure.
175 if tgen
.routers_have_failure():
176 pytest
.skip(tgen
.errors
)
178 reset_config_on_routers(tgen
)
180 step("Mgmt Commit check")
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",
190 result
= apply_raw_config(tgen
, raw_config
)
191 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
193 step("Mgmt Commit check")
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",
203 result
= apply_raw_config(tgen
, raw_config
)
204 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
206 step("verify that the route is not configured, as commit apply not done.")
214 "network": "1192.1.1.2/32",
221 tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
, expected
=False
225 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
227 write_test_footer(tc_name
)
230 def test_mgmt_commit_apply(request
):
232 Verify mgmt commit apply.
235 tc_name
= request
.node
.name
236 write_test_header(tc_name
)
238 # Don't run this test if we have any failure.
239 if tgen
.routers_have_failure():
240 pytest
.skip(tgen
.errors
)
242 reset_config_on_routers(tgen
)
244 step("Mgmt Commit apply with Valid Configuration")
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",
254 result
= apply_raw_config(tgen
, raw_config
)
255 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
257 step("Mgmt Commit apply with Invalid Configuration")
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",
267 result
= apply_raw_config(tgen
, raw_config
)
268 assert result
is not True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
270 step("verify that the route is configured")
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
)
278 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
280 write_test_footer(tc_name
)
283 def test_mgmt_commit_abort(request
):
285 Verify mgmt commit abort.
288 tc_name
= request
.node
.name
289 write_test_header(tc_name
)
291 # Don't run this test if we have any failure.
292 if tgen
.routers_have_failure():
293 pytest
.skip(tgen
.errors
)
295 reset_config_on_routers(tgen
)
297 step("Mgmt Commit abort")
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",
307 result
= apply_raw_config(tgen
, raw_config
)
308 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
310 step("verify that the route is not configured")
318 "network": "192.1.1.3/32",
325 tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
, expected
=False
329 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
331 write_test_footer(tc_name
)
334 def test_mgmt_delete_config(request
):
336 Verify mgmt delete config.
339 tc_name
= request
.node
.name
340 write_test_header(tc_name
)
342 # Don't run this test if we have any failure.
343 if tgen
.routers_have_failure():
344 pytest
.skip(tgen
.errors
)
346 reset_config_on_routers(tgen
)
348 step("Mgmt - Configure a static route using commit apply")
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",
359 result
= apply_raw_config(tgen
, raw_config
)
360 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
362 step("Verify that the route is added to RIB")
369 "network": "192.168.1.3/32",
375 result
= verify_rib(tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
)
378 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
380 step("Mgmt delete 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']",
390 result
= apply_raw_config(tgen
, raw_config
)
391 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
393 step("Verify that the route is deleted from RIB")
395 tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
, expected
=False
399 ), "Testcase {} : Failed" "Error: Routes is still present in RIB".format(tc_name
)
401 write_test_footer(tc_name
)
404 def test_mgmt_chaos_stop_start_frr(request
):
406 Kill mgmtd - verify that watch frr restarts.
409 tc_name
= request
.node
.name
410 write_test_header(tc_name
)
412 # Don't run this test if we have any failure.
413 if tgen
.routers_have_failure():
414 pytest
.skip(tgen
.errors
)
416 reset_config_on_routers(tgen
)
417 next_hop_ip
= populate_nh()
419 step("Configure Static route with next hop null 0")
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",
430 result
= apply_raw_config(tgen
, raw_config
)
431 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
433 step("verify that the route is configured and present in the zebra")
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
)
441 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
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
)
450 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
452 step("delete the configured route and ")
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']",
462 result
= apply_raw_config(tgen
, raw_config
)
463 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
465 step("verify that the route is deleted and deleted from zebra")
469 input_dict_4
= {"r1": {"static_routes": [{"network": "192.1.11.200/32"}]}}
471 tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
, expected
=False
475 ), "Testcase {} : Failed" "Error: Routes still present in RIB".format(tc_name
)
477 write_test_footer(tc_name
)
480 def test_mgmt_chaos_kill_daemon(request
):
482 Kill mgmtd - verify that static routes are intact
485 tc_name
= request
.node
.name
486 write_test_header(tc_name
)
488 # Don't run this test if we have any failure.
489 if tgen
.routers_have_failure():
490 pytest
.skip(tgen
.errors
)
492 reset_config_on_routers(tgen
)
493 next_hop_ip
= populate_nh()
495 step("Configure Static route with next hop null 0")
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",
506 result
= apply_raw_config(tgen
, raw_config
)
507 assert result
is True, "Testcase {} : Failed Error: {}".format(tc_name
, result
)
509 step("verify that the route is configured and present in the zebra")
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
)
517 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
519 step("Kill static daemon on R2.")
520 kill_router_daemons(tgen
, "r1", ["staticd"])
522 step("Bring up staticd daemon on R2.")
523 start_router_daemons(tgen
, "r1", ["staticd"])
525 step("Verify routes are intact in zebra.")
526 result
= verify_rib(tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
)
529 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
531 step("Kill mgmt daemon on R2.")
532 kill_router_daemons(tgen
, "r1", ["mgmtd"])
534 step("Bring up zebra daemon on R2.")
535 start_router_daemons(tgen
, "r1", ["mgmtd"])
537 step("Verify routes are intact in zebra.")
538 result
= verify_rib(tgen
, "ipv4", dut
, input_dict_4
, protocol
=protocol
)
541 ), "Testcase {} : Failed" "Error: Routes is missing in RIB".format(tc_name
)
543 write_test_footer(tc_name
)
546 if __name__
== "__main__":
547 args
= ["-s"] + sys
.argv
[1:]
548 sys
.exit(pytest
.main(args
))