mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 10:04:18 +00:00
Merge pull request #9569 from LabNConsulting/chopps/parallel-config-nonjson
tests: refactor parallel reset/load config for non-json
This commit is contained in:
commit
a76cd3242a
@ -40,85 +40,43 @@ test_bgp_auth.py: Test BGP Md5 Authentication
|
||||
setup is 3 routers with 3 links between each each link in a different vrf
|
||||
Default, blue and red respectively
|
||||
Tests check various fiddling with passwords and checking that the peer
|
||||
establishment is as expected and passwords are not leaked across sockets
|
||||
establishment is as expected and passwords are not leaked across sockets
|
||||
for bgp instances
|
||||
"""
|
||||
# pylint: disable=C0413
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
import pytest
|
||||
import sys
|
||||
from time import sleep
|
||||
|
||||
# Save the Current Working Directory to find configuration files.
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
# Import topogen and topotest helpers
|
||||
from lib import common_config
|
||||
from lib import topotest
|
||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||
import pytest
|
||||
from lib import common_config, topotest
|
||||
from lib.common_config import (
|
||||
FRRCFG_FILE,
|
||||
FRRCFG_BKUP_FILE,
|
||||
load_config_to_routers,
|
||||
reset_config_on_routers,
|
||||
save_initial_config_on_routers,
|
||||
reset_with_new_configs,
|
||||
)
|
||||
|
||||
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
|
||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||
|
||||
pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
|
||||
|
||||
|
||||
def reload_new_configs(tgen, *cflist):
|
||||
reset_config_on_routers(tgen)
|
||||
|
||||
routers = tgen.routers()
|
||||
for rname, router in routers.items():
|
||||
destname = "{}/{}/{}".format(tgen.logdir, rname, FRRCFG_FILE)
|
||||
wmode="w"
|
||||
for cfbase in cflist:
|
||||
confname = os.path.join(CWD, "{}/{}".format(rname, cfbase))
|
||||
with open(confname, "r") as cf:
|
||||
with open(destname, wmode) as df:
|
||||
df.write(cf.read())
|
||||
wmode="a"
|
||||
|
||||
# import pdb
|
||||
# pdb.set_trace()
|
||||
common_config.ROUTER_LIST = routers
|
||||
load_config_to_routers(tgen, routers, save_bkup=False)
|
||||
|
||||
|
||||
class InvalidCLIError(Exception):
|
||||
"""Raise when the CLI command is wrong"""
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
def build_topo(tgen):
|
||||
# Create routers
|
||||
tgen.add_router("R1")
|
||||
tgen.add_router("R2")
|
||||
tgen.add_router("R3")
|
||||
|
||||
# R1-R2 1
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||
# R1-R3 1
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||
# R2-R3 1
|
||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
||||
# R1-R2 2
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||
# R1-R3 2
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||
# R2-R3 2
|
||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
||||
# R1-R2 3
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||
# R1-R3 2
|
||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||
# R2-R3 2
|
||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
||||
|
||||
|
||||
@ -202,26 +160,15 @@ def setup_module(mod):
|
||||
|
||||
# For all registred routers, load the zebra configuration file
|
||||
for rname, router in router_list.items():
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_OSPF, os.path.join(CWD, "{}/empty.conf".format(rname))
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_BGP, os.path.join(CWD, "{}/empty.conf".format(rname))
|
||||
)
|
||||
router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
|
||||
router.load_config(TopoRouter.RD_OSPF)
|
||||
router.load_config(TopoRouter.RD_BGP)
|
||||
|
||||
# After loading the configurations, this function loads configured daemons.
|
||||
# After copying the configurations, this function loads configured daemons.
|
||||
tgen.start_router()
|
||||
|
||||
# Set the initial (saved) config to the zebra config. reset_config_on_routers
|
||||
# will use this config to reset to.
|
||||
routers = tgen.routers()
|
||||
for rname, router in routers.items():
|
||||
confname = os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
destname = "{}/{}/{}".format(tgen.logdir, rname, FRRCFG_BKUP_FILE)
|
||||
router.cmd_raises("cp {} {}".format(confname, destname))
|
||||
# Save the initial router config. reset_config_on_routers will return to this config.
|
||||
save_initial_config_on_routers(tgen)
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
@ -272,94 +219,30 @@ def print_diag(vrf):
|
||||
print(router.vtysh_cmd("show bgp {} neighbor".format(vrf_str(vrf))))
|
||||
|
||||
|
||||
def configure(conf_file):
|
||||
"configure from a file"
|
||||
@common_config.retry(retry_timeout=190)
|
||||
def _check_neigh_state(router, peer, state, vrf=""):
|
||||
"check BGP neighbor state on a router"
|
||||
|
||||
tgen = get_topogen()
|
||||
router_list = tgen.routers()
|
||||
for rname, router in router_list.items():
|
||||
with open(
|
||||
os.path.join(CWD, "{}/{}").format(router.name, conf_file), "r+"
|
||||
) as cfg:
|
||||
new_config = cfg.read()
|
||||
neigh_output = router.vtysh_cmd(
|
||||
"show bgp {} neighbors {} json".format(vrf_str(vrf), peer)
|
||||
)
|
||||
|
||||
output = router.vtysh_multicmd(new_config, pretty_output=False)
|
||||
for out_err in ERROR_LIST:
|
||||
if out_err.lower() in output.lower():
|
||||
raise InvalidCLIError("%s" % output)
|
||||
|
||||
|
||||
def clear_bgp():
|
||||
"clear bgp configuration for a vrf"
|
||||
|
||||
tgen = get_topogen()
|
||||
r1 = tgen.gears["R1"]
|
||||
r2 = tgen.gears["R2"]
|
||||
r3 = tgen.gears["R3"]
|
||||
|
||||
r1.vtysh_cmd("conf t\nno router bgp 65001")
|
||||
r2.vtysh_cmd("conf t\nno router bgp 65002")
|
||||
r3.vtysh_cmd("conf t\nno router bgp 65003")
|
||||
r1.vtysh_cmd("conf t\nno router bgp 65001 vrf blue")
|
||||
r2.vtysh_cmd("conf t\nno router bgp 65002 vrf blue")
|
||||
r3.vtysh_cmd("conf t\nno router bgp 65003 vrf blue")
|
||||
r1.vtysh_cmd("conf t\nno router bgp 65001 vrf red")
|
||||
r2.vtysh_cmd("conf t\nno router bgp 65002 vrf red")
|
||||
r3.vtysh_cmd("conf t\nno router bgp 65003 vrf red")
|
||||
|
||||
|
||||
def configure_bgp(conf_file):
|
||||
"configure bgp from file"
|
||||
|
||||
clear_bgp()
|
||||
configure(conf_file)
|
||||
|
||||
|
||||
def clear_ospf():
|
||||
"clear ospf configuration for a vrf"
|
||||
|
||||
tgen = get_topogen()
|
||||
router_list = tgen.routers()
|
||||
for rname, router in router_list.items():
|
||||
router.vtysh_cmd("conf t\nno router ospf")
|
||||
router.vtysh_cmd("conf t\nno router ospf vrf blue")
|
||||
router.vtysh_cmd("conf t\nno router ospf vrf red")
|
||||
|
||||
|
||||
def configure_ospf(conf_file):
|
||||
"configure bgp from file"
|
||||
|
||||
clear_ospf()
|
||||
configure(conf_file)
|
||||
peer_state = "Unknown"
|
||||
neigh_output_json = json.loads(neigh_output)
|
||||
if peer in neigh_output_json:
|
||||
peer_state = neigh_output_json[peer]["bgpState"]
|
||||
if peer_state == state:
|
||||
return True
|
||||
return "{} peer with {} expected state {} got {} ".format(
|
||||
router.name, peer, state, peer_state
|
||||
)
|
||||
|
||||
|
||||
def check_neigh_state(router, peer, state, vrf=""):
|
||||
"check BGP neighbor state on a router"
|
||||
|
||||
count = 0
|
||||
matched = False
|
||||
neigh_output = ""
|
||||
while count < 125:
|
||||
if vrf == "":
|
||||
neigh_output = router.vtysh_cmd("show bgp neighbors {} json".format(peer))
|
||||
else:
|
||||
neigh_output = router.vtysh_cmd(
|
||||
"show bgp vrf {} neighbors {} json".format(vrf, peer)
|
||||
)
|
||||
neigh_output_json = json.loads(neigh_output)
|
||||
if peer in neigh_output_json.keys():
|
||||
if neigh_output_json[peer]["bgpState"] == state:
|
||||
matched = True
|
||||
break
|
||||
count += 1
|
||||
sleep(1)
|
||||
|
||||
assertmsg = "{} could not peer {} state expected {} got {} ".format(
|
||||
router.name, peer, state, neigh_output_json[peer]["bgpState"]
|
||||
)
|
||||
if matched != True:
|
||||
print_diag(vrf)
|
||||
assert matched == True, assertmsg
|
||||
assertmsg = _check_neigh_state(router, peer, state, vrf)
|
||||
assert assertmsg is True, assertmsg
|
||||
|
||||
|
||||
def check_all_peers_established(vrf=""):
|
||||
@ -517,28 +400,21 @@ def check_vrf_peer_change_passwords(vrf="", prefix="no"):
|
||||
def test_default_peer_established(tgen):
|
||||
"default vrf 3 peers same password"
|
||||
|
||||
# configure_bgp("bgpd.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
check_all_peers_established()
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_default_peer_remove_passwords(tgen):
|
||||
"selectively remove passwords checking state"
|
||||
|
||||
# configure_bgp("bgpd.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
check_vrf_peer_remove_passwords()
|
||||
|
||||
|
||||
def test_default_peer_change_passwords(tgen):
|
||||
"selectively change passwords checking state"
|
||||
|
||||
# configure_bgp("bgpd.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||
check_vrf_peer_change_passwords()
|
||||
|
||||
|
||||
@ -549,11 +425,8 @@ def test_default_prefix_peer_established(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_prefix.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
check_all_peers_established()
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_prefix_peer_remove_passwords(tgen):
|
||||
@ -563,9 +436,7 @@ def test_prefix_peer_remove_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_prefix.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
check_vrf_peer_remove_passwords(prefix="yes")
|
||||
|
||||
|
||||
@ -576,9 +447,7 @@ def test_prefix_peer_change_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_prefix.conf")
|
||||
# configure_ospf("ospfd.conf")
|
||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||
check_vrf_peer_change_passwords(prefix="yes")
|
||||
|
||||
|
||||
@ -586,28 +455,21 @@ def test_vrf_peer_established(tgen):
|
||||
"default vrf 3 peers same password with VRF config"
|
||||
|
||||
# clean routers and load vrf config
|
||||
# configure_bgp("bgpd_vrf.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
check_all_peers_established("blue")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_vrf_peer_remove_passwords(tgen):
|
||||
"selectively remove passwords checking state with VRF config"
|
||||
|
||||
# configure_bgp("bgpd_vrf.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
check_vrf_peer_remove_passwords(vrf="blue")
|
||||
|
||||
|
||||
def test_vrf_peer_change_passwords(tgen):
|
||||
"selectively change passwords checking state with VRF config"
|
||||
|
||||
# configure_bgp("bgpd_vrf.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||
check_vrf_peer_change_passwords(vrf="blue")
|
||||
|
||||
|
||||
@ -618,9 +480,7 @@ def test_vrf_prefix_peer_established(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
check_all_peers_established("blue")
|
||||
|
||||
|
||||
@ -631,9 +491,7 @@ def test_vrf_prefix_peer_remove_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
|
||||
|
||||
|
||||
@ -644,47 +502,36 @@ def test_vrf_prefix_peer_change_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
||||
|
||||
|
||||
def test_multiple_vrf_peer_established(tgen):
|
||||
"default vrf 3 peers same password with multiple VRFs"
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
check_all_peers_established("blue")
|
||||
check_all_peers_established("red")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_multiple_vrf_peer_remove_passwords(tgen):
|
||||
"selectively remove passwords checking state with multiple VRFs"
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
check_vrf_peer_remove_passwords("blue")
|
||||
check_all_peers_established("red")
|
||||
check_vrf_peer_remove_passwords("red")
|
||||
check_all_peers_established("blue")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_multiple_vrf_peer_change_passwords(tgen):
|
||||
"selectively change passwords checking state with multiple VRFs"
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||
check_vrf_peer_change_passwords("blue")
|
||||
check_all_peers_established("red")
|
||||
check_vrf_peer_change_passwords("red")
|
||||
check_all_peers_established("blue")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_multiple_vrf_prefix_peer_established(tgen):
|
||||
@ -694,12 +541,9 @@ def test_multiple_vrf_prefix_peer_established(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
check_all_peers_established("blue")
|
||||
check_all_peers_established("red")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_multiple_vrf_prefix_peer_remove_passwords(tgen):
|
||||
@ -709,14 +553,11 @@ def test_multiple_vrf_prefix_peer_remove_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
|
||||
check_all_peers_established("red")
|
||||
check_vrf_peer_remove_passwords(vrf="red", prefix="yes")
|
||||
check_all_peers_established("blue")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_multiple_vrf_prefix_peer_change_passwords(tgen):
|
||||
@ -726,14 +567,11 @@ def test_multiple_vrf_prefix_peer_change_passwords(tgen):
|
||||
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||
return
|
||||
|
||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
||||
# configure_ospf("ospfd_multi_vrf.conf")
|
||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
||||
check_all_peers_established("red")
|
||||
check_vrf_peer_change_passwords(vrf="red", prefix="yes")
|
||||
check_all_peers_established("blue")
|
||||
# tgen.mininet_cli()
|
||||
|
||||
|
||||
def test_memory_leak(tgen):
|
||||
|
@ -255,6 +255,7 @@ def pytest_configure(config):
|
||||
cli_level = config.getini("log_cli_level")
|
||||
if cli_level is not None:
|
||||
config.option.log_cli_level = cli_level
|
||||
|
||||
# ---------------------------------------
|
||||
# Record our options in global dictionary
|
||||
# ---------------------------------------
|
||||
@ -329,6 +330,12 @@ def setup_session_auto():
|
||||
logger.debug("After the run (is_worker: %s)", is_worker)
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
module = item.parent.module
|
||||
script_dir = os.path.abspath(os.path.dirname(module.__file__))
|
||||
os.environ["PYTEST_TOPOTEST_SCRIPTDIR"] = script_dir
|
||||
|
||||
|
||||
def pytest_runtest_makereport(item, call):
|
||||
"Log all assert messages to default logger with error level"
|
||||
|
||||
|
@ -49,7 +49,6 @@ FRRCFG_FILE = "frr_json.conf"
|
||||
FRRCFG_BKUP_FILE = "frr_json_initial.conf"
|
||||
|
||||
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
|
||||
ROUTER_LIST = []
|
||||
|
||||
####
|
||||
CD = os.path.dirname(os.path.realpath(__file__))
|
||||
@ -471,6 +470,40 @@ def check_router_status(tgen):
|
||||
return True
|
||||
|
||||
|
||||
def save_initial_config_on_routers(tgen):
|
||||
"""Save current configuration on routers to FRRCFG_BKUP_FILE.
|
||||
|
||||
FRRCFG_BKUP_FILE is the file that will be restored when `reset_config_on_routers()`
|
||||
is called.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
* `tgen` : Topogen object
|
||||
"""
|
||||
router_list = tgen.routers()
|
||||
target_cfg_fmt = tgen.logdir + "/{}/frr_json_initial.conf"
|
||||
|
||||
# Get all running configs in parallel
|
||||
procs = {}
|
||||
for rname in router_list:
|
||||
logger.info("Fetching running config for router %s", rname)
|
||||
procs[rname] = router_list[rname].popen(
|
||||
["/usr/bin/env", "vtysh", "-c", "show running-config no-header"],
|
||||
stdin=None,
|
||||
stdout=open(target_cfg_fmt.format(rname), "w"),
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
for rname, p in procs.items():
|
||||
_, error = p.communicate()
|
||||
if p.returncode:
|
||||
logger.error(
|
||||
"Get running config for %s failed %d: %s", rname, p.returncode, error
|
||||
)
|
||||
raise InvalidCLIError(
|
||||
"vtysh show running error on {}: {}".format(rname, error)
|
||||
)
|
||||
|
||||
|
||||
def reset_config_on_routers(tgen, routerName=None):
|
||||
"""
|
||||
Resets configuration on routers to the snapshot created using input JSON
|
||||
@ -490,8 +523,12 @@ def reset_config_on_routers(tgen, routerName=None):
|
||||
# Trim the router list if needed
|
||||
router_list = tgen.routers()
|
||||
if routerName:
|
||||
if (routerName not in ROUTER_LIST) or (routerName not in router_list):
|
||||
logger.debug("Exiting API: reset_config_on_routers: no routers")
|
||||
if routerName not in router_list:
|
||||
logger.warning(
|
||||
"Exiting API: reset_config_on_routers: no router %s",
|
||||
routerName,
|
||||
exc_info=True,
|
||||
)
|
||||
return True
|
||||
router_list = {routerName: router_list[routerName]}
|
||||
|
||||
@ -622,6 +659,44 @@ def reset_config_on_routers(tgen, routerName=None):
|
||||
return True
|
||||
|
||||
|
||||
def prep_load_config_to_routers(tgen, *config_name_list):
|
||||
"""Create common config for `load_config_to_routers`.
|
||||
|
||||
The common config file is constructed from the list of sub-config files passed as
|
||||
position arguments to this function. Each entry in `config_name_list` is looked for
|
||||
under the router sub-directory in the test directory and those files are
|
||||
concatenated together to create the common config. e.g.,
|
||||
|
||||
# Routers are "r1" and "r2", test file is `example/test_example_foo.py`
|
||||
prepare_load_config_to_routers(tgen, "bgpd.conf", "ospfd.conf")
|
||||
|
||||
When the above call is made the files in
|
||||
|
||||
example/r1/bgpd.conf
|
||||
example/r1/ospfd.conf
|
||||
|
||||
Are concat'd together into a single config file that will be loaded on r1, and
|
||||
|
||||
example/r2/bgpd.conf
|
||||
example/r2/ospfd.conf
|
||||
|
||||
Are concat'd together into a single config file that will be loaded on r2 when
|
||||
the call to `load_config_to_routers` is made.
|
||||
"""
|
||||
|
||||
routers = tgen.routers()
|
||||
for rname, router in routers.items():
|
||||
destname = "{}/{}/{}".format(tgen.logdir, rname, FRRCFG_FILE)
|
||||
wmode = "w"
|
||||
for cfbase in config_name_list:
|
||||
script_dir = os.environ["PYTEST_TOPOTEST_SCRIPTDIR"]
|
||||
confname = os.path.join(script_dir, "{}/{}".format(rname, cfbase))
|
||||
with open(confname, "r") as cf:
|
||||
with open(destname, wmode) as df:
|
||||
df.write(cf.read())
|
||||
wmode = "a"
|
||||
|
||||
|
||||
def load_config_to_routers(tgen, routers, save_bkup=False):
|
||||
"""
|
||||
Loads configuration on routers from the file FRRCFG_FILE.
|
||||
@ -644,7 +719,7 @@ def load_config_to_routers(tgen, routers, save_bkup=False):
|
||||
base_router_list = tgen.routers()
|
||||
router_list = {}
|
||||
for router in routers:
|
||||
if (router not in ROUTER_LIST) or (router not in base_router_list):
|
||||
if router not in base_router_list:
|
||||
continue
|
||||
router_list[router] = base_router_list[router]
|
||||
|
||||
@ -759,6 +834,21 @@ def load_config_to_router(tgen, routerName, save_bkup=False):
|
||||
return load_config_to_routers(tgen, [routerName], save_bkup)
|
||||
|
||||
|
||||
def reset_with_new_configs(tgen, *cflist):
|
||||
"""Reset the router to initial config, then load new configs.
|
||||
|
||||
Resets routers to the initial config state (see `save_initial_config_on_routers()
|
||||
and `reset_config_on_routers()` `), then concat list of router sub-configs together
|
||||
and load onto the routers (see `prep_load_config_to_routers()` and
|
||||
`load_config_to_routers()`)
|
||||
"""
|
||||
routers = tgen.routers()
|
||||
|
||||
reset_config_on_routers(tgen)
|
||||
prep_load_config_to_routers(tgen, *cflist)
|
||||
load_config_to_routers(tgen, tgen.routers(), save_bkup=False)
|
||||
|
||||
|
||||
def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
|
||||
"""
|
||||
API to get the link local ipv6 address of a particular interface using
|
||||
@ -882,20 +972,19 @@ def start_topology(tgen, daemon=None):
|
||||
* `tgen` : topogen object
|
||||
"""
|
||||
|
||||
global ROUTER_LIST
|
||||
# Starting topology
|
||||
tgen.start_topology()
|
||||
|
||||
# Starting daemons
|
||||
|
||||
router_list = tgen.routers()
|
||||
ROUTER_LIST = sorted(
|
||||
routers_sorted = sorted(
|
||||
router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0))
|
||||
)
|
||||
|
||||
linux_ver = ""
|
||||
router_list = tgen.routers()
|
||||
for rname in ROUTER_LIST:
|
||||
for rname in routers_sorted:
|
||||
router = router_list[rname]
|
||||
|
||||
# It will help in debugging the failures, will give more details on which
|
||||
@ -1034,11 +1123,11 @@ def topo_daemons(tgen, topo=None):
|
||||
topo = tgen.json_topo
|
||||
|
||||
router_list = tgen.routers()
|
||||
ROUTER_LIST = sorted(
|
||||
routers_sorted = sorted(
|
||||
router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0))
|
||||
)
|
||||
|
||||
for rtr in ROUTER_LIST:
|
||||
for rtr in routers_sorted:
|
||||
if "ospf" in topo["routers"][rtr] and "ospfd" not in daemon_list:
|
||||
daemon_list.append("ospfd")
|
||||
|
||||
|
@ -786,13 +786,16 @@ class TopoRouter(TopoGear):
|
||||
return self.net.checkCapability(daemonstr, param)
|
||||
|
||||
def load_config(self, daemon, source=None, param=None):
|
||||
"""
|
||||
Loads daemon configuration from the specified source
|
||||
"""Loads daemon configuration from the specified source
|
||||
Possible daemon values are: TopoRouter.RD_ZEBRA, TopoRouter.RD_RIP,
|
||||
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
|
||||
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
|
||||
TopoRouter.RD_PIM, TopoRouter.RD_PBR, TopoRouter.RD_SNMP.
|
||||
|
||||
Possible `source` values are `None` for an empty config file, a path name which is
|
||||
used directly, or a file name with no path components which is first looked for
|
||||
directly and then looked for under a sub-directory named after router.
|
||||
|
||||
This API unfortunately allows for source to not exist for any and
|
||||
all routers.
|
||||
"""
|
||||
|
@ -44,8 +44,6 @@ from lib.ospf import create_router_ospf, create_router_ospf6
|
||||
from lib.pim import create_igmp_config, create_pim_config
|
||||
from lib.topolog import logger
|
||||
|
||||
ROUTER_LIST = []
|
||||
|
||||
|
||||
def build_topo_from_json(tgen, topo=None):
|
||||
"""
|
||||
@ -58,26 +56,26 @@ def build_topo_from_json(tgen, topo=None):
|
||||
if topo is None:
|
||||
topo = tgen.json_topo
|
||||
|
||||
ROUTER_LIST = sorted(
|
||||
router_list = sorted(
|
||||
topo["routers"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
||||
)
|
||||
|
||||
SWITCH_LIST = []
|
||||
switch_list = []
|
||||
if "switches" in topo:
|
||||
SWITCH_LIST = sorted(
|
||||
switch_list = sorted(
|
||||
topo["switches"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
||||
)
|
||||
|
||||
listRouters = sorted(ROUTER_LIST[:])
|
||||
listSwitches = sorted(SWITCH_LIST[:])
|
||||
listRouters = sorted(router_list[:])
|
||||
listSwitches = sorted(switch_list[:])
|
||||
listAllRouters = deepcopy(listRouters)
|
||||
dictSwitches = {}
|
||||
|
||||
for routerN in ROUTER_LIST:
|
||||
for routerN in router_list:
|
||||
logger.info("Topo: Add router {}".format(routerN))
|
||||
tgen.add_router(routerN)
|
||||
|
||||
for switchN in SWITCH_LIST:
|
||||
for switchN in switch_list:
|
||||
logger.info("Topo: Add switch {}".format(switchN))
|
||||
dictSwitches[switchN] = tgen.add_switch(switchN)
|
||||
|
||||
|
@ -1488,7 +1488,25 @@ class Router(Node):
|
||||
return True
|
||||
|
||||
def loadConf(self, daemon, source=None, param=None):
|
||||
"""Enabled and set config for a daemon.
|
||||
|
||||
Arranges for loading of daemon configuration from the specified source. Possible
|
||||
`source` values are `None` for an empty config file, a path name which is used
|
||||
directly, or a file name with no path components which is first looked for
|
||||
directly and then looked for under a sub-directory named after router.
|
||||
"""
|
||||
|
||||
# Unfortunately this API allowsfor source to not exist for any and all routers.
|
||||
if source:
|
||||
head, tail = os.path.split(source)
|
||||
if not head and not self.path_exists(tail):
|
||||
script_dir = os.environ["PYTEST_TOPOTEST_SCRIPTDIR"]
|
||||
router_relative = os.path.join(script_dir, self.name, tail)
|
||||
if self.path_exists(router_relative):
|
||||
source = router_relative
|
||||
self.logger.info(
|
||||
"using router relative configuration: {}".format(source)
|
||||
)
|
||||
|
||||
# print "Daemons before:", self.daemons
|
||||
if daemon in self.daemons.keys():
|
||||
@ -1497,6 +1515,7 @@ class Router(Node):
|
||||
self.daemons_options[daemon] = param
|
||||
conf_file = "/etc/{}/{}.conf".format(self.routertype, daemon)
|
||||
if source is None or not os.path.exists(source):
|
||||
self.cmd_raises("rm -f " + conf_file)
|
||||
self.cmd_raises("touch " + conf_file)
|
||||
else:
|
||||
self.cmd_raises("cp {} {}".format(source, conf_file))
|
||||
|
Loading…
Reference in New Issue
Block a user