mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-29 16:24:55 +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
@ -43,82 +43,40 @@ 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
|
for bgp instances
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=C0413
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import platform
|
import platform
|
||||||
import pytest
|
import sys
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
# Save the Current Working Directory to find configuration files.
|
import pytest
|
||||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
from lib import common_config, topotest
|
||||||
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
|
|
||||||
from lib.common_config import (
|
from lib.common_config import (
|
||||||
FRRCFG_FILE,
|
save_initial_config_on_routers,
|
||||||
FRRCFG_BKUP_FILE,
|
reset_with_new_configs,
|
||||||
load_config_to_routers,
|
|
||||||
reset_config_on_routers,
|
|
||||||
)
|
)
|
||||||
|
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||||
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
|
|
||||||
|
|
||||||
pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
|
pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
|
||||||
|
|
||||||
|
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||||
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"""
|
|
||||||
|
|
||||||
|
|
||||||
def build_topo(tgen):
|
def build_topo(tgen):
|
||||||
# Create routers
|
|
||||||
tgen.add_router("R1")
|
tgen.add_router("R1")
|
||||||
tgen.add_router("R2")
|
tgen.add_router("R2")
|
||||||
tgen.add_router("R3")
|
tgen.add_router("R3")
|
||||||
|
|
||||||
# R1-R2 1
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||||
# R1-R3 1
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||||
# R2-R3 1
|
|
||||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
||||||
# R1-R2 2
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||||
# R1-R3 2
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||||
# R2-R3 2
|
|
||||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
||||||
# R1-R2 3
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R2"])
|
||||||
# R1-R3 2
|
|
||||||
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
tgen.add_link(tgen.gears["R1"], tgen.gears["R3"])
|
||||||
# R2-R3 2
|
|
||||||
tgen.add_link(tgen.gears["R2"], tgen.gears["R3"])
|
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 all registred routers, load the zebra configuration file
|
||||||
for rname, router in router_list.items():
|
for rname, router in router_list.items():
|
||||||
router.load_config(
|
router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf")
|
||||||
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
router.load_config(TopoRouter.RD_OSPF)
|
||||||
)
|
router.load_config(TopoRouter.RD_BGP)
|
||||||
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))
|
|
||||||
)
|
|
||||||
|
|
||||||
# After loading the configurations, this function loads configured daemons.
|
# After copying the configurations, this function loads configured daemons.
|
||||||
tgen.start_router()
|
tgen.start_router()
|
||||||
|
|
||||||
# Set the initial (saved) config to the zebra config. reset_config_on_routers
|
# Save the initial router config. reset_config_on_routers will return to this config.
|
||||||
# will use this config to reset to.
|
save_initial_config_on_routers(tgen)
|
||||||
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))
|
|
||||||
|
|
||||||
|
|
||||||
def teardown_module(mod):
|
def teardown_module(mod):
|
||||||
@ -272,94 +219,30 @@ def print_diag(vrf):
|
|||||||
print(router.vtysh_cmd("show bgp {} neighbor".format(vrf_str(vrf))))
|
print(router.vtysh_cmd("show bgp {} neighbor".format(vrf_str(vrf))))
|
||||||
|
|
||||||
|
|
||||||
def configure(conf_file):
|
@common_config.retry(retry_timeout=190)
|
||||||
"configure from a file"
|
def _check_neigh_state(router, peer, state, vrf=""):
|
||||||
|
"check BGP neighbor state on a router"
|
||||||
|
|
||||||
tgen = get_topogen()
|
neigh_output = router.vtysh_cmd(
|
||||||
router_list = tgen.routers()
|
"show bgp {} neighbors {} json".format(vrf_str(vrf), peer)
|
||||||
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()
|
|
||||||
|
|
||||||
output = router.vtysh_multicmd(new_config, pretty_output=False)
|
peer_state = "Unknown"
|
||||||
for out_err in ERROR_LIST:
|
neigh_output_json = json.loads(neigh_output)
|
||||||
if out_err.lower() in output.lower():
|
if peer in neigh_output_json:
|
||||||
raise InvalidCLIError("%s" % output)
|
peer_state = neigh_output_json[peer]["bgpState"]
|
||||||
|
if peer_state == state:
|
||||||
|
return True
|
||||||
def clear_bgp():
|
return "{} peer with {} expected state {} got {} ".format(
|
||||||
"clear bgp configuration for a vrf"
|
router.name, peer, state, peer_state
|
||||||
|
)
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
def check_neigh_state(router, peer, state, vrf=""):
|
def check_neigh_state(router, peer, state, vrf=""):
|
||||||
"check BGP neighbor state on a router"
|
"check BGP neighbor state on a router"
|
||||||
|
|
||||||
count = 0
|
assertmsg = _check_neigh_state(router, peer, state, vrf)
|
||||||
matched = False
|
assert assertmsg is True, assertmsg
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
def check_all_peers_established(vrf=""):
|
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):
|
def test_default_peer_established(tgen):
|
||||||
"default vrf 3 peers same password"
|
"default vrf 3 peers same password"
|
||||||
|
|
||||||
# configure_bgp("bgpd.conf")
|
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
|
||||||
check_all_peers_established()
|
check_all_peers_established()
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_default_peer_remove_passwords(tgen):
|
def test_default_peer_remove_passwords(tgen):
|
||||||
"selectively remove passwords checking state"
|
"selectively remove passwords checking state"
|
||||||
|
|
||||||
# configure_bgp("bgpd.conf")
|
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
|
||||||
check_vrf_peer_remove_passwords()
|
check_vrf_peer_remove_passwords()
|
||||||
|
|
||||||
|
|
||||||
def test_default_peer_change_passwords(tgen):
|
def test_default_peer_change_passwords(tgen):
|
||||||
"selectively change passwords checking state"
|
"selectively change passwords checking state"
|
||||||
|
|
||||||
# configure_bgp("bgpd.conf")
|
reset_with_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd.conf", "ospfd.conf")
|
|
||||||
check_vrf_peer_change_passwords()
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
|
||||||
check_all_peers_established()
|
check_all_peers_established()
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_prefix_peer_remove_passwords(tgen):
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
|
||||||
check_vrf_peer_remove_passwords(prefix="yes")
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
||||||
# configure_ospf("ospfd.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_prefix.conf", "ospfd.conf")
|
|
||||||
check_vrf_peer_change_passwords(prefix="yes")
|
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"
|
"default vrf 3 peers same password with VRF config"
|
||||||
|
|
||||||
# clean routers and load vrf config
|
# clean routers and load vrf config
|
||||||
# configure_bgp("bgpd_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_vrf_peer_remove_passwords(tgen):
|
def test_vrf_peer_remove_passwords(tgen):
|
||||||
"selectively remove passwords checking state with VRF config"
|
"selectively remove passwords checking state with VRF config"
|
||||||
|
|
||||||
# configure_bgp("bgpd_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
|
||||||
check_vrf_peer_remove_passwords(vrf="blue")
|
check_vrf_peer_remove_passwords(vrf="blue")
|
||||||
|
|
||||||
|
|
||||||
def test_vrf_peer_change_passwords(tgen):
|
def test_vrf_peer_change_passwords(tgen):
|
||||||
"selectively change passwords checking state with VRF config"
|
"selectively change passwords checking state with VRF config"
|
||||||
|
|
||||||
# configure_bgp("bgpd_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf.conf", "ospfd_vrf.conf")
|
|
||||||
check_vrf_peer_change_passwords(vrf="blue")
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
|
||||||
check_all_peers_established("blue")
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
|
||||||
check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
||||||
# configure_ospf("ospfd_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_vrf_prefix.conf", "ospfd_vrf.conf")
|
|
||||||
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_peer_established(tgen):
|
def test_multiple_vrf_peer_established(tgen):
|
||||||
"default vrf 3 peers same password with multiple VRFs"
|
"default vrf 3 peers same password with multiple VRFs"
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_peer_remove_passwords(tgen):
|
def test_multiple_vrf_peer_remove_passwords(tgen):
|
||||||
"selectively remove passwords checking state with multiple VRFs"
|
"selectively remove passwords checking state with multiple VRFs"
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_vrf_peer_remove_passwords("blue")
|
check_vrf_peer_remove_passwords("blue")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
check_vrf_peer_remove_passwords("red")
|
check_vrf_peer_remove_passwords("red")
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_peer_change_passwords(tgen):
|
def test_multiple_vrf_peer_change_passwords(tgen):
|
||||||
"selectively change passwords checking state with multiple VRFs"
|
"selectively change passwords checking state with multiple VRFs"
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_vrf_peer_change_passwords("blue")
|
check_vrf_peer_change_passwords("blue")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
check_vrf_peer_change_passwords("red")
|
check_vrf_peer_change_passwords("red")
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_prefix_peer_established(tgen):
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_prefix_peer_remove_passwords(tgen):
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
|
check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
check_vrf_peer_remove_passwords(vrf="red", prefix="yes")
|
check_vrf_peer_remove_passwords(vrf="red", prefix="yes")
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_vrf_prefix_peer_change_passwords(tgen):
|
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:
|
if topotest.version_cmp(platform.release(), "5.3") < 0:
|
||||||
return
|
return
|
||||||
|
|
||||||
# configure_bgp("bgpd_multi_vrf_prefix.conf")
|
reset_with_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
||||||
# configure_ospf("ospfd_multi_vrf.conf")
|
|
||||||
reload_new_configs(tgen, "bgpd_multi_vrf_prefix.conf", "ospfd_multi_vrf.conf")
|
|
||||||
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
|
||||||
check_all_peers_established("red")
|
check_all_peers_established("red")
|
||||||
check_vrf_peer_change_passwords(vrf="red", prefix="yes")
|
check_vrf_peer_change_passwords(vrf="red", prefix="yes")
|
||||||
check_all_peers_established("blue")
|
check_all_peers_established("blue")
|
||||||
# tgen.mininet_cli()
|
|
||||||
|
|
||||||
|
|
||||||
def test_memory_leak(tgen):
|
def test_memory_leak(tgen):
|
||||||
|
@ -255,6 +255,7 @@ def pytest_configure(config):
|
|||||||
cli_level = config.getini("log_cli_level")
|
cli_level = config.getini("log_cli_level")
|
||||||
if cli_level is not None:
|
if cli_level is not None:
|
||||||
config.option.log_cli_level = cli_level
|
config.option.log_cli_level = cli_level
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# Record our options in global dictionary
|
# Record our options in global dictionary
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
@ -329,6 +330,12 @@ def setup_session_auto():
|
|||||||
logger.debug("After the run (is_worker: %s)", is_worker)
|
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):
|
def pytest_runtest_makereport(item, call):
|
||||||
"Log all assert messages to default logger with error level"
|
"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"
|
FRRCFG_BKUP_FILE = "frr_json_initial.conf"
|
||||||
|
|
||||||
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
|
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
|
||||||
ROUTER_LIST = []
|
|
||||||
|
|
||||||
####
|
####
|
||||||
CD = os.path.dirname(os.path.realpath(__file__))
|
CD = os.path.dirname(os.path.realpath(__file__))
|
||||||
@ -471,6 +470,40 @@ def check_router_status(tgen):
|
|||||||
return True
|
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):
|
def reset_config_on_routers(tgen, routerName=None):
|
||||||
"""
|
"""
|
||||||
Resets configuration on routers to the snapshot created using input JSON
|
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
|
# Trim the router list if needed
|
||||||
router_list = tgen.routers()
|
router_list = tgen.routers()
|
||||||
if routerName:
|
if routerName:
|
||||||
if (routerName not in ROUTER_LIST) or (routerName not in router_list):
|
if routerName not in router_list:
|
||||||
logger.debug("Exiting API: reset_config_on_routers: no routers")
|
logger.warning(
|
||||||
|
"Exiting API: reset_config_on_routers: no router %s",
|
||||||
|
routerName,
|
||||||
|
exc_info=True,
|
||||||
|
)
|
||||||
return True
|
return True
|
||||||
router_list = {routerName: router_list[routerName]}
|
router_list = {routerName: router_list[routerName]}
|
||||||
|
|
||||||
@ -622,6 +659,44 @@ def reset_config_on_routers(tgen, routerName=None):
|
|||||||
return True
|
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):
|
def load_config_to_routers(tgen, routers, save_bkup=False):
|
||||||
"""
|
"""
|
||||||
Loads configuration on routers from the file FRRCFG_FILE.
|
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()
|
base_router_list = tgen.routers()
|
||||||
router_list = {}
|
router_list = {}
|
||||||
for router in routers:
|
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
|
continue
|
||||||
router_list[router] = base_router_list[router]
|
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)
|
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):
|
def get_frr_ipv6_linklocal(tgen, router, intf=None, vrf=None):
|
||||||
"""
|
"""
|
||||||
API to get the link local ipv6 address of a particular interface using
|
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
|
* `tgen` : topogen object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
global ROUTER_LIST
|
|
||||||
# Starting topology
|
# Starting topology
|
||||||
tgen.start_topology()
|
tgen.start_topology()
|
||||||
|
|
||||||
# Starting daemons
|
# Starting daemons
|
||||||
|
|
||||||
router_list = tgen.routers()
|
router_list = tgen.routers()
|
||||||
ROUTER_LIST = sorted(
|
routers_sorted = sorted(
|
||||||
router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0))
|
router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0))
|
||||||
)
|
)
|
||||||
|
|
||||||
linux_ver = ""
|
linux_ver = ""
|
||||||
router_list = tgen.routers()
|
router_list = tgen.routers()
|
||||||
for rname in ROUTER_LIST:
|
for rname in routers_sorted:
|
||||||
router = router_list[rname]
|
router = router_list[rname]
|
||||||
|
|
||||||
# It will help in debugging the failures, will give more details on which
|
# 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
|
topo = tgen.json_topo
|
||||||
|
|
||||||
router_list = tgen.routers()
|
router_list = tgen.routers()
|
||||||
ROUTER_LIST = sorted(
|
routers_sorted = sorted(
|
||||||
router_list.keys(), key=lambda x: int(re_search("[0-9]+", x).group(0))
|
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:
|
if "ospf" in topo["routers"][rtr] and "ospfd" not in daemon_list:
|
||||||
daemon_list.append("ospfd")
|
daemon_list.append("ospfd")
|
||||||
|
|
||||||
|
@ -786,13 +786,16 @@ class TopoRouter(TopoGear):
|
|||||||
return self.net.checkCapability(daemonstr, param)
|
return self.net.checkCapability(daemonstr, param)
|
||||||
|
|
||||||
def load_config(self, daemon, source=None, param=None):
|
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,
|
Possible daemon values are: TopoRouter.RD_ZEBRA, TopoRouter.RD_RIP,
|
||||||
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
|
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
|
||||||
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
|
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
|
||||||
TopoRouter.RD_PIM, TopoRouter.RD_PBR, TopoRouter.RD_SNMP.
|
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
|
This API unfortunately allows for source to not exist for any and
|
||||||
all routers.
|
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.pim import create_igmp_config, create_pim_config
|
||||||
from lib.topolog import logger
|
from lib.topolog import logger
|
||||||
|
|
||||||
ROUTER_LIST = []
|
|
||||||
|
|
||||||
|
|
||||||
def build_topo_from_json(tgen, topo=None):
|
def build_topo_from_json(tgen, topo=None):
|
||||||
"""
|
"""
|
||||||
@ -58,26 +56,26 @@ def build_topo_from_json(tgen, topo=None):
|
|||||||
if topo is None:
|
if topo is None:
|
||||||
topo = tgen.json_topo
|
topo = tgen.json_topo
|
||||||
|
|
||||||
ROUTER_LIST = sorted(
|
router_list = sorted(
|
||||||
topo["routers"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
topo["routers"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
||||||
)
|
)
|
||||||
|
|
||||||
SWITCH_LIST = []
|
switch_list = []
|
||||||
if "switches" in topo:
|
if "switches" in topo:
|
||||||
SWITCH_LIST = sorted(
|
switch_list = sorted(
|
||||||
topo["switches"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
topo["switches"].keys(), key=lambda x: int(re_search(r"\d+", x).group(0))
|
||||||
)
|
)
|
||||||
|
|
||||||
listRouters = sorted(ROUTER_LIST[:])
|
listRouters = sorted(router_list[:])
|
||||||
listSwitches = sorted(SWITCH_LIST[:])
|
listSwitches = sorted(switch_list[:])
|
||||||
listAllRouters = deepcopy(listRouters)
|
listAllRouters = deepcopy(listRouters)
|
||||||
dictSwitches = {}
|
dictSwitches = {}
|
||||||
|
|
||||||
for routerN in ROUTER_LIST:
|
for routerN in router_list:
|
||||||
logger.info("Topo: Add router {}".format(routerN))
|
logger.info("Topo: Add router {}".format(routerN))
|
||||||
tgen.add_router(routerN)
|
tgen.add_router(routerN)
|
||||||
|
|
||||||
for switchN in SWITCH_LIST:
|
for switchN in switch_list:
|
||||||
logger.info("Topo: Add switch {}".format(switchN))
|
logger.info("Topo: Add switch {}".format(switchN))
|
||||||
dictSwitches[switchN] = tgen.add_switch(switchN)
|
dictSwitches[switchN] = tgen.add_switch(switchN)
|
||||||
|
|
||||||
|
@ -1488,7 +1488,25 @@ class Router(Node):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def loadConf(self, daemon, source=None, param=None):
|
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.
|
# 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
|
# print "Daemons before:", self.daemons
|
||||||
if daemon in self.daemons.keys():
|
if daemon in self.daemons.keys():
|
||||||
@ -1497,6 +1515,7 @@ class Router(Node):
|
|||||||
self.daemons_options[daemon] = param
|
self.daemons_options[daemon] = param
|
||||||
conf_file = "/etc/{}/{}.conf".format(self.routertype, daemon)
|
conf_file = "/etc/{}/{}.conf".format(self.routertype, daemon)
|
||||||
if source is None or not os.path.exists(source):
|
if source is None or not os.path.exists(source):
|
||||||
|
self.cmd_raises("rm -f " + conf_file)
|
||||||
self.cmd_raises("touch " + conf_file)
|
self.cmd_raises("touch " + conf_file)
|
||||||
else:
|
else:
|
||||||
self.cmd_raises("cp {} {}".format(source, conf_file))
|
self.cmd_raises("cp {} {}".format(source, conf_file))
|
||||||
|
Loading…
Reference in New Issue
Block a user