diff options
author | Donatas Abraitis <donatas@opensourcerouting.org> | 2023-06-13 10:10:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-13 10:10:18 +0200 |
commit | e0db9a05bd43eafbd6e2b2bf84aaa7ac31b415fa (patch) | |
tree | 1a7d330c62e2a0bacd77a2a574852c5debd89dbb /tests | |
parent | Merge pull request #13704 from donaldsharp/flowspec_support_bundle (diff) | |
parent | tests: add mgmtd config test (diff) | |
download | frr-e0db9a05bd43eafbd6e2b2bf84aaa7ac31b415fa.tar.xz frr-e0db9a05bd43eafbd6e2b2bf84aaa7ac31b415fa.zip |
Merge pull request #13763 from LabNConsulting/mgmtd/simplify
fix 'exit' bug in config file processing, et al.
Diffstat (limited to 'tests')
17 files changed, 485 insertions, 0 deletions
diff --git a/tests/topotests/mgmt_config/r1/early-end-zebra.conf b/tests/topotests/mgmt_config/r1/early-end-zebra.conf new file mode 100644 index 000000000..44a2f9682 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-end-zebra.conf @@ -0,0 +1,6 @@ +allow-external-route-update +end +ip multicast rpf-lookup-mode urib-only +end +ip table range 2 3 +end
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-end.conf b/tests/topotests/mgmt_config/r1/early-end.conf new file mode 100644 index 000000000..3aacad647 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-end.conf @@ -0,0 +1,8 @@ +ip route 15.1.0.0/24 101.0.0.2 +end +ip route 15.2.0.0/24 101.0.0.2 +end +ip route 15.3.0.0/24 101.0.0.2 +end +ip route 15.4.0.0/24 101.0.0.2 +end
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-end2-zebra.conf b/tests/topotests/mgmt_config/r1/early-end2-zebra.conf new file mode 100644 index 000000000..37619d52a --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-end2-zebra.conf @@ -0,0 +1,7 @@ +conf t +allow-external-route-update +end +ip multicast rpf-lookup-mode urib-only +end +ip table range 2 3 +end
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-end2.conf b/tests/topotests/mgmt_config/r1/early-end2.conf new file mode 100644 index 000000000..229ccc741 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-end2.conf @@ -0,0 +1,9 @@ +conf t +ip route 16.1.0.0/24 101.0.0.2 +end +ip route 16.2.0.0/24 101.0.0.2 +end +ip route 16.3.0.0/24 101.0.0.2 +end +ip route 16.4.0.0/24 101.0.0.2 +end
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-exit-zebra.conf b/tests/topotests/mgmt_config/r1/early-exit-zebra.conf new file mode 100644 index 000000000..44f202dbc --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-exit-zebra.conf @@ -0,0 +1,6 @@ +allow-external-route-update +exit +ip multicast rpf-lookup-mode urib-only +exit +ip table range 2 3 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-exit.conf b/tests/topotests/mgmt_config/r1/early-exit.conf new file mode 100644 index 000000000..c6a52df5d --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-exit.conf @@ -0,0 +1,8 @@ +ip route 13.1.0.0/24 101.0.0.2 +exit +ip route 13.2.0.0/24 101.0.0.2 +exit +ip route 13.3.0.0/24 101.0.0.2 +exit +ip route 13.4.0.0/24 101.0.0.2 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-exit2-zebra.conf b/tests/topotests/mgmt_config/r1/early-exit2-zebra.conf new file mode 100644 index 000000000..c7109bfd3 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-exit2-zebra.conf @@ -0,0 +1,7 @@ +conf t +allow-external-route-update +exit +ip multicast rpf-lookup-mode urib-only +exit +ip table range 2 3 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/early-exit2.conf b/tests/topotests/mgmt_config/r1/early-exit2.conf new file mode 100644 index 000000000..79510c0ae --- /dev/null +++ b/tests/topotests/mgmt_config/r1/early-exit2.conf @@ -0,0 +1,9 @@ +conf t +ip route 14.1.0.0/24 101.0.0.2 +exit +ip route 14.2.0.0/24 101.0.0.2 +exit +ip route 14.3.0.0/24 101.0.0.2 +exit +ip route 14.4.0.0/24 101.0.0.2 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/mgmtd.conf b/tests/topotests/mgmt_config/r1/mgmtd.conf new file mode 100644 index 000000000..318de765c --- /dev/null +++ b/tests/topotests/mgmt_config/r1/mgmtd.conf @@ -0,0 +1,11 @@ +debug northbound notifications +debug northbound libyang +debug northbound events +debug northbound callbacks +debug mgmt backend datastore frontend transaction +debug mgmt client backend +debug mgmt client frontend + +ip route 12.0.0.0/24 101.0.0.2 + +ipv6 route 2012::/48 2101::2
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/normal-exit.conf b/tests/topotests/mgmt_config/r1/normal-exit.conf new file mode 100644 index 000000000..c6a52df5d --- /dev/null +++ b/tests/topotests/mgmt_config/r1/normal-exit.conf @@ -0,0 +1,8 @@ +ip route 13.1.0.0/24 101.0.0.2 +exit +ip route 13.2.0.0/24 101.0.0.2 +exit +ip route 13.3.0.0/24 101.0.0.2 +exit +ip route 13.4.0.0/24 101.0.0.2 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/one-exit-zebra.conf b/tests/topotests/mgmt_config/r1/one-exit-zebra.conf new file mode 100644 index 000000000..0c3845970 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/one-exit-zebra.conf @@ -0,0 +1,3 @@ +allow-external-route-update +exit +ip multicast rpf-lookup-mode urib-only diff --git a/tests/topotests/mgmt_config/r1/one-exit.conf b/tests/topotests/mgmt_config/r1/one-exit.conf new file mode 100644 index 000000000..47147d44e --- /dev/null +++ b/tests/topotests/mgmt_config/r1/one-exit.conf @@ -0,0 +1,3 @@ +ip route 20.1.0.0/24 101.0.0.2 +exit +ip route 20.2.0.0/24 101.0.0.2 diff --git a/tests/topotests/mgmt_config/r1/one-exit2-zebra.conf b/tests/topotests/mgmt_config/r1/one-exit2-zebra.conf new file mode 100644 index 000000000..34acb76d9 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/one-exit2-zebra.conf @@ -0,0 +1,4 @@ +conf t +allow-external-route-update +exit +ip multicast rpf-lookup-mode urib-only
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/r1/one-exit2.conf b/tests/topotests/mgmt_config/r1/one-exit2.conf new file mode 100644 index 000000000..262339a85 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/one-exit2.conf @@ -0,0 +1,4 @@ +conf t +ip route 21.1.0.0/24 101.0.0.2 +exit +ip route 21.2.0.0/24 101.0.0.2 diff --git a/tests/topotests/mgmt_config/r1/zebra.conf b/tests/topotests/mgmt_config/r1/zebra.conf new file mode 100644 index 000000000..f3264efb0 --- /dev/null +++ b/tests/topotests/mgmt_config/r1/zebra.conf @@ -0,0 +1,7 @@ +log timestamp precision 6 +log file frr-r1.log debug + +interface r1-eth0 + ip address 101.0.0.1/24 + ipv6 address 2101::1/64 +exit
\ No newline at end of file diff --git a/tests/topotests/mgmt_config/test_config.py b/tests/topotests/mgmt_config/test_config.py new file mode 100644 index 000000000..b07ed8f7f --- /dev/null +++ b/tests/topotests/mgmt_config/test_config.py @@ -0,0 +1,385 @@ +# -*- coding: utf-8 eval: (blacken-mode 1) -*- +# SPDX-License-Identifier: ISC +# +# June 10 2023, Christian Hopps <chopps@labn.net> +# +# Copyright (c) 2023, LabN Consulting, L.L.C. +# +""" +Test mgmtd parsing of configs. + +So: + +MGMTD matches zebra: + +one exit file: ONE: vty -f file +one exit redir: ONE: vty < file +early exit file: ONE: vty -f file +early exit redir: ONE: vty < file +early end file: ALL: vty -f file +early end redir: ONE: vty < file + +Raw tests: + +FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_file - AssertionError: vtysh < didn't work after exit +FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_redir - AssertionError: vtysh < didn't work after exit +FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_file - AssertionError: vtysh -f didn't work after 1 exit +FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_redir - AssertionError: vtysh < didn't work after 1 exits +FAILED mgmt_config/test_config.py::test_mgmtd_early_end_redir - AssertionError: vtysh < didn't work after 1 end + +FAILED mgmt_config/test_config.py::test_zebra_one_exit_file - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_one_exit_redir - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_exit_file - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_exit_redir - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_end_redir - AssertionError: zebra second conf missing + +Before fixed: + +one exit file: NONE: vty -f file +early exit file: NONE: vty -f file + +FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_file - AssertionError: vtysh -f didn't work before exit +FAILED mgmt_config/test_config.py::test_mgmtd_one_exit_redir - AssertionError: vtysh < didn't work after exit +FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_file - AssertionError: vtysh -f didn't work before exit +FAILED mgmt_config/test_config.py::test_mgmtd_early_exit_redir - AssertionError: vtysh < didn't work after 1 exits +FAILED mgmt_config/test_config.py::test_mgmtd_early_end_redir - AssertionError: vtysh < didn't work after 1 end + +FAILED mgmt_config/test_config.py::test_zebra_one_exit_file - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_one_exit_redir - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_exit_file - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_exit_redir - AssertionError: zebra second conf missing +FAILED mgmt_config/test_config.py::test_zebra_early_end_redir - AssertionError: zebra second conf missing + +""" +import ipaddress +import logging +import os +import re +from pathlib import Path + +import pytest +from lib.common_config import retry, step +from lib.topogen import Topogen, TopoRouter + +# pytestmark = [pytest.mark.staticd, pytest.mark.mgmtd] +pytestmark = [pytest.mark.staticd] + + +@retry(retry_timeout=1, initial_wait=0.1) +def check_kernel(r1, prefix, expected=True): + net = ipaddress.ip_network(prefix) + if net.version == 6: + kernel = r1.cmd_nostatus("ip -6 route show", warn=not expected) + else: + kernel = r1.cmd_nostatus("ip -4 route show", warn=not expected) + + logging.debug("checking kernel routing table:\n%0.1920s", kernel) + route = f"{str(net)}(?: nhid [0-9]+)?.*proto (static|196)" + m = re.search(route, kernel) + if expected and not m: + return f"Failed to find \n'{route}'\n in \n'{kernel:.1920}'" + elif not expected and m: + return f"Failed found \n'{route}'\n in \n'{kernel:.1920}'" + return None + + +@pytest.fixture(scope="module") +def tgen(request): + "Setup/Teardown the environment and provide tgen argument to tests" + + topodef = {"s1": ("r1",)} + + tgen = Topogen(topodef, request.module.__name__) + tgen.start_topology() + + # configure mgmtd using current mgmtd config file + tgen.gears["r1"].load_config(TopoRouter.RD_ZEBRA, "zebra.conf") + tgen.gears["r1"].load_config(TopoRouter.RD_MGMTD) + + tgen.start_router() + yield tgen + tgen.stop_topology() + + +def save_log_snippet(logfile, content, savepath=None): + os.sync() + os.sync() + os.sync() + + with open(logfile, encoding="utf-8") as f: + buf = f.read() + assert content == buf[: len(content)] + newcontent = buf[len(content) :] + + if savepath: + with open(savepath, "w", encoding="utf-8") as f: + f.write(newcontent) + + return buf + + +def mapname(lname): + return lname.replace(".conf", "") + "-log.txt" + + +logbuf = "" + + +@pytest.fixture(scope="module") +def r1(tgen): + return tgen.gears["r1"].net + + +@pytest.fixture(scope="module") +def confdir(): + return Path(os.environ["PYTEST_TOPOTEST_SCRIPTDIR"]) / "r1" + + +@pytest.fixture(scope="module") +def tempdir(r1): + return Path(r1.rundir) + + +@pytest.fixture(scope="module") +def logpath(tempdir): + return tempdir / "mgmtd.log" + + +@pytest.fixture(autouse=True, scope="function") +def cleanup_config(r1, tempdir, logpath): + global logbuf + + logbuf = save_log_snippet(logpath, logbuf, "/dev/null") + + yield + + r1.cmd_nostatus("vtysh -c 'conf t' -c 'no allow-external-route-update'") + r1.cmd_nostatus("vtysh -c 'conf t' -c 'no ip multicast rpf-lookup-mode urib-only'") + r1.cmd_nostatus("vtysh -c 'conf t' -c 'no ip table range 2 3'") + + logbuf = save_log_snippet(logpath, logbuf, "/dev/null") + + +def test_staticd_startup(r1): + r1.cmd_nostatus( + "vtysh -c 'debug mgmt client frontend' " + "-c 'debug mgmt client backend' " + "-c 'debug mgmt backend frontend datastore transaction'" + ) + step("Verifying routes are present on r1") + result = check_kernel(r1, "12.0.0.0/24", retry_timeout=3.0) + assert result is None + + +def test_mgmtd_one_exit_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "one-exit.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "20.1.0.0/24") + result2 = check_kernel(r1, "20.2.0.0/24") + + assert result1 is None, "vtysh -f didn't work before exit" + assert result2 is not None, "vtysh < worked after exit, unexpected" + + +def test_mgmtd_one_exit_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "one-exit2.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "21.1.0.0/24") + result2 = check_kernel(r1, "21.2.0.0/24") + + assert result1 is None, "vtysh < didn't work before exit" + assert result2 is not None, "vtysh < worked after exit, unexpected" + + +def test_mgmtd_early_exit_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-exit.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "13.1.0.0/24") + result2 = check_kernel(r1, "13.2.0.0/24") + result3 = check_kernel(r1, "13.3.0.0/24") + + assert result1 is None, "vtysh -f didn't work before exit" + assert result2 is not None, "vtysh -f worked after 1 exit, unexpected" + assert result3 is not None, "vtysh -f worked after 2 exit, unexpected" + + +def test_mgmtd_early_exit_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-exit2.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "14.1.0.0/24") + result2 = check_kernel(r1, "14.2.0.0/24") + result3 = check_kernel(r1, "14.3.0.0/24") + + assert result1 is None, "vtysh < didn't work before exit" + assert result2 is not None, "vtysh < worked after 1 exits, unexpected" + assert result3 is not None, "vtysh < worked after 2 exits, unexpected" + + +def test_mgmtd_early_end_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-end.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "15.1.0.0/24") + result2 = check_kernel(r1, "15.2.0.0/24") + result3 = check_kernel(r1, "15.3.0.0/24") + + assert result1 is None, "vtysh -f didn't work before end" + assert result2 is None, "vtysh -f didn't work after 1 end" + assert result3 is None, "vtysh -f didn't work after 2 ends" + + +def test_mgmtd_early_end_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-end2.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + result1 = check_kernel(r1, "16.1.0.0/24") + result2 = check_kernel(r1, "16.2.0.0/24") + result3 = check_kernel(r1, "16.3.0.0/24") + + assert result1 is None, "vtysh < didn't work before end" + assert result2 is not None, "vtysh < worked after 1 end, unexpected" + assert result3 is not None, "vtysh < worked after 2 end, unexpected" + + +# +# Zebra +# + + +def test_zebra_one_exit_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "one-exit-zebra.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" not in showrun + ), "zebra second conf present, unexpected" + + +def test_zebra_one_exit_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "one-exit2-zebra.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" not in showrun + ), "zebra second conf present, unexpected" + + +def test_zebra_early_exit_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-exit-zebra.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" not in showrun + ), "zebra second conf present, unexpected" + assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected" + + +def test_zebra_early_exit_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-exit2-zebra.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" not in showrun + ), "zebra second conf present, unexpected" + assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected" + + +def test_zebra_early_end_file(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-end-zebra.conf" + step(f"load {conf} file with vtysh -f ") + output = r1.cmd_nostatus(f"vtysh -f {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" in showrun + ), "zebra second conf missing" + assert "ip table range 2 3" in showrun, "zebra third missing" + + +def test_zebra_early_end_redir(r1, confdir, tempdir, logpath): + global logbuf + + conf = "early-end2-zebra.conf" + step(f"Redirect {conf} file into vtysh") + output = r1.cmd_nostatus(f"vtysh < {confdir / conf}") + logbuf = save_log_snippet(logpath, logbuf, tempdir / mapname(conf)) + print(output) + + showrun = r1.cmd_nostatus("vtysh -c 'show running'") + + assert "allow-external-route-update" in showrun, "zebra conf missing" + assert ( + "ip multicast rpf-lookup-mode urib-only" not in showrun + ), "zebra second conf present, unexpected" + assert "ip table range 2 3" not in showrun, "zebra third conf present, unexpected" diff --git a/tests/topotests/mgmt_startup/test_config.py b/tests/topotests/mgmt_startup/test_cfgfile_var.py index 6a54f7191..6a54f7191 100644 --- a/tests/topotests/mgmt_startup/test_config.py +++ b/tests/topotests/mgmt_startup/test_cfgfile_var.py |