From 9c21096df23718d5fdf9408b512345941e5d4f64 Mon Sep 17 00:00:00 2001 From: vitthalmagadum Date: Wed, 5 Mar 2025 01:16:40 -0500 Subject: [PATCH 1/2] added minimum time duration check for the tests --- anta/tests/routing/bgp.py | 49 ++- examples/tests.yaml | 4 + tests/units/anta_tests/routing/test_bgp.py | 397 +++++++++++++++++++++ 3 files changed, 445 insertions(+), 5 deletions(-) diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py index 7522c2549..a51fc7fb7 100644 --- a/anta/tests/routing/bgp.py +++ b/anta/tests/routing/bgp.py @@ -146,6 +146,7 @@ class VerifyBGPPeersHealth(AntaTest): - Confirms that the AFI/SAFI state is `negotiated`. - Checks that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` to `False`. + - Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -156,6 +157,7 @@ class VerifyBGPPeersHealth(AntaTest): - Any BGP session is not in the `Established` state. - The AFI/SAFI state is not 'negotiated' for any peer. - Any TCP message queue (input or output) is not empty when `check_tcp_queues` is `True` (default). + - Any BGP session is not established for specified minimum duration. Examples -------- @@ -163,6 +165,7 @@ class VerifyBGPPeersHealth(AntaTest): anta.tests.routing: bgp: - VerifyBGPPeersHealth: + minimum_established_time: 10000 address_families: - afi: "evpn" - afi: "ipv4" @@ -181,6 +184,8 @@ class VerifyBGPPeersHealth(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeersHealth test.""" + minimum_established_time: int | None = None + """Minimum established time(seconds) for all the neighbors.""" address_families: list[BgpAddressFamily] """List of BGP address families.""" BgpAfi: ClassVar[type[BgpAfi]] = BgpAfi @@ -213,6 +218,10 @@ def test(self) -> None: self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - Session state is not established - State: {peer['state']}") continue + if self.inputs.minimum_established_time and (act_time := peer["establishedTime"]) < self.inputs.minimum_established_time: + msg = f"Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - {msg}") + # Check if the AFI/SAFI state is negotiated capability_status = get_value(peer, f"neighborCapabilities.multiprotocolCaps.{address_family.eos_key}") if not _check_bgp_neighbor_capability(capability_status): @@ -238,6 +247,7 @@ class VerifyBGPSpecificPeers(AntaTest): - Confirms that the AFI/SAFI state is `negotiated`. - Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` to `False`. + - Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -248,6 +258,7 @@ class VerifyBGPSpecificPeers(AntaTest): - The BGP session for a peer is not in the `Established` state. - The AFI/SAFI state is not `negotiated` for a peer. - Any TCP message queue (input or output) is not empty for a peer when `check_tcp_queues` is `True` (default). + - Any BGP session is not established for specified minimum duration. Examples -------- @@ -255,6 +266,7 @@ class VerifyBGPSpecificPeers(AntaTest): anta.tests.routing: bgp: - VerifyBGPSpecificPeers: + minimum_established_time: 10000 address_families: - afi: "evpn" peers: @@ -276,6 +288,8 @@ class VerifyBGPSpecificPeers(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPSpecificPeers test.""" + minimum_established_time: int | None = None + """Minimum established time(seconds) for all the neighbors.""" address_families: list[BgpAddressFamily] """List of BGP address families.""" BgpAfi: ClassVar[type[BgpAfi]] = BgpAfi @@ -316,6 +330,10 @@ def test(self) -> None: self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session state is not established - State: {peer_data['state']}") continue + if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: + msg = f"Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + self.result.is_failure(f"{address_family} Peer: {peer_ip} - {msg}") + # Check if the AFI/SAFI state is negotiated capability_status = get_value(peer_data, f"neighborCapabilities.multiprotocolCaps.{address_family.eos_key}") if not capability_status: @@ -325,11 +343,10 @@ def test(self) -> None: self.result.is_failure(f"{address_family} Peer: {peer_ip} - AFI/SAFI state is not negotiated - {format_data(capability_status)}") # Check the TCP session message queues - if address_family.check_tcp_queues: - inq = peer_data["peerTcpInfo"]["inputQueueLength"] - outq = peer_data["peerTcpInfo"]["outputQueueLength"] - if inq != 0 or outq != 0: - self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}") + inq = peer_data["peerTcpInfo"]["inputQueueLength"] + outq = peer_data["peerTcpInfo"]["outputQueueLength"] + if address_family.check_tcp_queues and (inq != 0 or outq != 0): + self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}") class VerifyBGPPeerSession(AntaTest): @@ -341,6 +358,7 @@ class VerifyBGPPeerSession(AntaTest): 2. Checks that the BGP session is in the `Established` state. 3. Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` global flag to `False`. + 4. Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -348,10 +366,12 @@ class VerifyBGPPeerSession(AntaTest): - All specified peers are found in the BGP configuration. - All peers sessions state are `Established`. - All peers have empty TCP message queues if `check_tcp_queues` is `True` (default). + - All peers are established for specified minimum duration. * Failure: If any of the following occur: - A specified peer is not found in the BGP configuration. - A peer's session state is not `Established`. - A peer has non-empty TCP message queues (input or output) when `check_tcp_queues` is `True`. + - Any BGP session is not established for specified minimum duration. Examples -------- @@ -359,6 +379,7 @@ class VerifyBGPPeerSession(AntaTest): anta.tests.routing: bgp: - VerifyBGPPeerSession: + minimum_established_time: 10000 check_tcp_queues: false bgp_peers: - peer_address: 10.1.0.1 @@ -378,6 +399,8 @@ class VerifyBGPPeerSession(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeerSession test.""" + minimum_established_time: int | None = None + """Minimum established time(seconds) for all the neighbors.""" check_tcp_queues: bool = True """Flag to check if the TCP session queues are empty for all BGP peers. Defaults to `True`.""" bgp_peers: list[BgpPeer] @@ -404,6 +427,11 @@ def test(self) -> None: self.result.is_failure(f"{peer} - Session state is not established - State: {peer_data['state']}") continue + if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: + self.result.is_failure( + f"{peer} - Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + ) + # Check the TCP session message queues if self.inputs.check_tcp_queues: inq = peer_data["peerTcpInfo"]["inputQueueLength"] @@ -1427,6 +1455,7 @@ class VerifyBGPPeerSessionRibd(AntaTest): 2. Checks that the BGP session is in the `Established` state. 3. Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` global flag to `False`. + 4. Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -1434,10 +1463,12 @@ class VerifyBGPPeerSessionRibd(AntaTest): - All specified peers are found in the BGP configuration. - All peers sessions state are `Established`. - All peers have empty TCP message queues if `check_tcp_queues` is `True` (default). + - All peers are established for specified minimum duration. * Failure: If any of the following occur: - A specified peer is not found in the BGP configuration. - A peer's session state is not `Established`. - A peer has non-empty TCP message queues (input or output) when `check_tcp_queues` is `True`. + - Any BGP session is not established for specified minimum duration. Examples -------- @@ -1445,6 +1476,7 @@ class VerifyBGPPeerSessionRibd(AntaTest): anta.tests.routing: bgp: - VerifyBGPPeerSessionRibd: + minimum_established_time: 10000 check_tcp_queues: false bgp_peers: - peer_address: 10.1.0.1 @@ -1464,6 +1496,8 @@ class VerifyBGPPeerSessionRibd(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeerSessionRibd test.""" + minimum_established_time: int | None = None + """Minimum established time(seconds) for all the neighbors.""" check_tcp_queues: bool = True """Flag to check if the TCP session queues are empty for all BGP peers. Defaults to `True`.""" bgp_peers: list[BgpPeer] @@ -1490,6 +1524,11 @@ def test(self) -> None: self.result.is_failure(f"{peer} - Session state is not established - State: {peer_data['state']}") continue + if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: + self.result.is_failure( + f"{peer} - Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + ) + # Check the TCP session message queues if self.inputs.check_tcp_queues: inq_stat = peer_data["peerTcpInfo"]["inputQueueLength"] diff --git a/examples/tests.yaml b/examples/tests.yaml index 6e5d88c66..3f28c5099 100644 --- a/examples/tests.yaml +++ b/examples/tests.yaml @@ -472,6 +472,7 @@ anta.tests.routing.bgp: vrf: default - VerifyBGPPeerSession: # Verifies the session state of BGP IPv4 peer(s). + minimum_established_time: 10000 check_tcp_queues: false bgp_peers: - peer_address: 10.1.0.1 @@ -484,6 +485,7 @@ anta.tests.routing.bgp: vrf: DEV - VerifyBGPPeerSessionRibd: # Verifies the session state of BGP IPv4 peer(s). + minimum_established_time: 10000 check_tcp_queues: false bgp_peers: - peer_address: 10.1.0.1 @@ -503,6 +505,7 @@ anta.tests.routing.bgp: - inUpdErrWithdraw - VerifyBGPPeersHealth: # Verifies the health of BGP peers for given address families. + minimum_established_time: 10000 address_families: - afi: "evpn" - afi: "ipv4" @@ -553,6 +556,7 @@ anta.tests.routing.bgp: origin: Incomplete - VerifyBGPSpecificPeers: # Verifies the health of specific BGP peer(s) for given address families. + minimum_established_time: 10000 address_families: - afi: "evpn" peers: diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py index ee26155f3..3dfa80008 100644 --- a/tests/units/anta_tests/routing/test_bgp.py +++ b/tests/units/anta_tests/routing/test_bgp.py @@ -473,6 +473,54 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo }, "expected": {"result": "success"}, }, + { + "name": "success-min-established-time", + "test": VerifyBGPPeersHealth, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + { + "peerAddress": "10.100.0.13", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"l2VpnEvpn": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + "DEV": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + } + } + ], + "inputs": { + "minimum_established_time": 10000, + "address_families": [ + {"afi": "evpn"}, + {"afi": "ipv4", "safi": "unicast", "vrf": "default"}, + {"afi": "ipv4", "safi": "unicast", "vrf": "DEV"}, + ], + }, + "expected": {"result": "success"}, + }, { "name": "failure-vrf-not-configured", "test": VerifyBGPPeersHealth, @@ -694,6 +742,61 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo ], }, }, + { + "name": "failure-min-established-time", + "test": VerifyBGPPeersHealth, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + { + "peerAddress": "10.100.0.13", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"l2VpnEvpn": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + "DEV": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + } + } + ], + "inputs": { + "minimum_established_time": 10000, + "address_families": [ + {"afi": "evpn"}, + {"afi": "ipv4", "safi": "unicast", "vrf": "default"}, + {"afi": "ipv4", "safi": "unicast", "vrf": "DEV"}, + ], + }, + "expected": { + "result": "failure", + "messages": [ + "AFI: evpn Peer: 10.100.0.13 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: DEV Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + ], + }, + }, { "name": "success", "test": VerifyBGPSpecificPeers, @@ -738,6 +841,54 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo }, "expected": {"result": "success"}, }, + { + "name": "success-min-established-time", + "test": VerifyBGPSpecificPeers, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + { + "peerAddress": "10.100.0.13", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"l2VpnEvpn": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.14", + "state": "Established", + "establishedTime": 169883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + } + } + ], + "inputs": { + "minimum_established_time": 10000, + "address_families": [ + {"afi": "ipv4", "safi": "unicast", "peers": ["10.100.0.12"]}, + {"afi": "evpn", "peers": ["10.100.0.13"]}, + {"afi": "ipv4", "safi": "unicast", "vrf": "MGMT", "peers": ["10.100.0.14"]}, + ], + }, + "expected": {"result": "success"}, + }, { "name": "failure-peer-not-configured", "test": VerifyBGPSpecificPeers, @@ -977,6 +1128,61 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo ], }, }, + { + "name": "failure-min-established-time", + "test": VerifyBGPSpecificPeers, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.12", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + { + "peerAddress": "10.100.0.13", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"l2VpnEvpn": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.14", + "state": "Established", + "establishedTime": 9883, + "neighborCapabilities": {"multiprotocolCaps": {"ipv4Unicast": {"advertised": True, "received": True, "enabled": True}}}, + "peerTcpInfo": {"state": "ESTABLISHED", "outputQueueLength": 0, "inputQueueLength": 0}, + }, + ] + }, + } + } + ], + "inputs": { + "minimum_established_time": 10000, + "address_families": [ + {"afi": "ipv4", "safi": "unicast", "peers": ["10.100.0.12"]}, + {"afi": "evpn", "peers": ["10.100.0.13"]}, + {"afi": "ipv4", "safi": "unicast", "vrf": "MGMT", "peers": ["10.100.0.14"]}, + ], + }, + "expected": { + "result": "failure", + "messages": [ + "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: evpn Peer: 10.100.0.13 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + ], + }, + }, { "name": "success", "test": VerifyBGPExchangedRoutes, @@ -4202,6 +4408,51 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo }, "expected": {"result": "success"}, }, + { + "name": "success-min-established-time", + "test": VerifyBGPPeerSession, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.8", + "state": "Established", + "establishedTime": 169883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.9", + "state": "Established", + "establishedTime": 169883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + }, + }, + ], + "inputs": { + "minimum_established_time": 10000, + "check_tcp_queues": True, + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.9", "vrf": "MGMT"}, + ], + }, + "expected": {"result": "success"}, + }, { "name": "failure-peer-not-found", "test": VerifyBGPPeerSession, @@ -4329,6 +4580,57 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo ], }, }, + { + "name": "failure-min-established-time", + "test": VerifyBGPPeerSession, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.8", + "state": "Established", + "establishedTime": 9883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.9", + "state": "Established", + "establishedTime": 9883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + }, + }, + ], + "inputs": { + "minimum_established_time": 10000, + "check_tcp_queues": True, + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.9", "vrf": "MGMT"}, + ], + }, + "expected": { + "result": "failure", + "messages": [ + "Peer: 10.100.0.8 VRF: default - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.9 VRF: MGMT - Session is not established for expected time - Expected: 10000s Actual: 9883s", + ], + }, + }, { "name": "success", "test": VerifyBGPPeerGroup, @@ -4562,6 +4864,51 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo { "name": "success-check-tcp-queues", "test": VerifyBGPPeerSessionRibd, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.8", + "state": "Established", + "establishedTime": 169883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.9", + "state": "Established", + "establishedTime": 169883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + }, + }, + ], + "inputs": { + "minimum_established_time": 10000, + "check_tcp_queues": True, + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.9", "vrf": "MGMT"}, + ], + }, + "expected": {"result": "success"}, + }, + { + "name": "success-min-established-time", + "test": VerifyBGPPeerSessionRibd, "eos_data": [ { "vrfs": { @@ -4728,6 +5075,56 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo ], }, }, + { + "name": "failure-min-established-time", + "test": VerifyBGPPeerSessionRibd, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "10.100.0.8", + "state": "Established", + "establishedTime": 9883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "10.100.0.9", + "state": "Established", + "establishedTime": 9883, + "peerTcpInfo": { + "outputQueueLength": 0, + "inputQueueLength": 0, + }, + } + ] + }, + }, + }, + ], + "inputs": { + "minimum_established_time": 10000, + "bgp_peers": [ + {"peer_address": "10.100.0.8", "vrf": "default"}, + {"peer_address": "10.100.0.9", "vrf": "MGMT"}, + ], + }, + "expected": { + "result": "failure", + "messages": [ + "Peer: 10.100.0.8 VRF: default - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.9 VRF: MGMT - Session is not established for expected time - Expected: 10000s Actual: 9883s", + ], + }, + }, { "name": "success-no-check-tcp-queues", "test": VerifyBGPPeersHealthRibd, From 486dcb7fe3f2f7e2ab20a098d99265c33b5829b1 Mon Sep 17 00:00:00 2001 From: vitthalmagadum Date: Wed, 12 Mar 2025 01:04:13 -0400 Subject: [PATCH 2/2] addressed review comments: updated docs, failure msgs --- anta/tests/routing/bgp.py | 58 ++++++++++------------ tests/units/anta_tests/routing/test_bgp.py | 24 +++++---- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py index 9a92029b0..afd61a173 100644 --- a/anta/tests/routing/bgp.py +++ b/anta/tests/routing/bgp.py @@ -9,7 +9,7 @@ from typing import Any, ClassVar, TypeVar -from pydantic import field_validator +from pydantic import PositiveInt, field_validator from anta.input_models.routing.bgp import BgpAddressFamily, BgpAfi, BgpNeighbor, BgpPeer, BgpRoute, BgpVrf, VxlanEndpoint from anta.models import AntaCommand, AntaTemplate, AntaTest @@ -142,11 +142,10 @@ class VerifyBGPPeersHealth(AntaTest): 1. Validates that the VRF is configured. 2. Checks if there are any peers for the given AFI/SAFI. 3. For each relevant peer: - - Verifies that the BGP session is in the `Established` state. + - Verifies that the BGP session is `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. - Confirms that the AFI/SAFI state is `negotiated`. - Checks that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` to `False`. - - Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -154,10 +153,10 @@ class VerifyBGPPeersHealth(AntaTest): * Failure: If any of the following occur: - The specified VRF is not configured. - No peers are found for a given AFI/SAFI. - - Any BGP session is not in the `Established` state. + - A peer's session state is not `Established` or if specified, has not remained established for at least the duration specified by + the `minimum_established_time`. - The AFI/SAFI state is not 'negotiated' for any peer. - Any TCP message queue (input or output) is not empty when `check_tcp_queues` is `True` (default). - - Any BGP session is not established for specified minimum duration. Examples -------- @@ -184,8 +183,8 @@ class VerifyBGPPeersHealth(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeersHealth test.""" - minimum_established_time: int | None = None - """Minimum established time(seconds) for all the neighbors.""" + minimum_established_time: PositiveInt | None = None + """Minimum established time (seconds) for all the BGP sessions.""" address_families: list[BgpAddressFamily] """List of BGP address families.""" BgpAfi: ClassVar[type[BgpAfi]] = BgpAfi @@ -219,7 +218,7 @@ def test(self) -> None: continue if self.inputs.minimum_established_time and (act_time := peer["establishedTime"]) < self.inputs.minimum_established_time: - msg = f"Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + msg = f"BGP session not established for the minimum required duration - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - {msg}") # Check if the AFI/SAFI state is negotiated @@ -243,11 +242,10 @@ class VerifyBGPSpecificPeers(AntaTest): 1. Confirms that the specified VRF is configured. 2. For each specified peer: - Verifies that the peer is found in the BGP configuration. - - Checks that the BGP session is in the `Established` state. + - Verifies that the BGP session is `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. - Confirms that the AFI/SAFI state is `negotiated`. - Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` to `False`. - - Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- @@ -255,10 +253,10 @@ class VerifyBGPSpecificPeers(AntaTest): * Failure: If any of the following occur: - The specified VRF is not configured. - A specified peer is not found in the BGP configuration. - - The BGP session for a peer is not in the `Established` state. + - A peer's session state is not `Established` or if specified, has not remained established for at least the duration specified by + the `minimum_established_time`. - The AFI/SAFI state is not `negotiated` for a peer. - Any TCP message queue (input or output) is not empty for a peer when `check_tcp_queues` is `True` (default). - - Any BGP session is not established for specified minimum duration. Examples -------- @@ -288,8 +286,8 @@ class VerifyBGPSpecificPeers(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPSpecificPeers test.""" - minimum_established_time: int | None = None - """Minimum established time(seconds) for all the neighbors.""" + minimum_established_time: PositiveInt | None = None + """Minimum established time (seconds) for all the BGP sessions.""" address_families: list[BgpAddressFamily] """List of BGP address families.""" BgpAfi: ClassVar[type[BgpAfi]] = BgpAfi @@ -331,7 +329,7 @@ def test(self) -> None: continue if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: - msg = f"Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + msg = f"BGP session not established for the minimum required duration - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" self.result.is_failure(f"{address_family} Peer: {peer_ip} - {msg}") # Check if the AFI/SAFI state is negotiated @@ -355,23 +353,22 @@ class VerifyBGPPeerSession(AntaTest): This test performs the following checks for each specified peer: 1. Verifies that the peer is found in its VRF in the BGP configuration. - 2. Checks that the BGP session is in the `Established` state. + 2. Verifies that the BGP session is `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. 3. Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` global flag to `False`. - 4. Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- * Success: If all of the following conditions are met: - All specified peers are found in the BGP configuration. - - All peers sessions state are `Established`. + - All peers sessions state are `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. - All peers have empty TCP message queues if `check_tcp_queues` is `True` (default). - All peers are established for specified minimum duration. * Failure: If any of the following occur: - A specified peer is not found in the BGP configuration. - - A peer's session state is not `Established`. + - A peer's session state is not `Established` or if specified, has not remained established for at least the duration specified by + the `minimum_established_time`. - A peer has non-empty TCP message queues (input or output) when `check_tcp_queues` is `True`. - - Any BGP session is not established for specified minimum duration. Examples -------- @@ -399,8 +396,8 @@ class VerifyBGPPeerSession(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeerSession test.""" - minimum_established_time: int | None = None - """Minimum established time(seconds) for all the neighbors.""" + minimum_established_time: PositiveInt | None = None + """Minimum established time (seconds) for all the BGP sessions.""" check_tcp_queues: bool = True """Flag to check if the TCP session queues are empty for all BGP peers. Defaults to `True`.""" bgp_peers: list[BgpPeer] @@ -429,7 +426,7 @@ def test(self) -> None: if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: self.result.is_failure( - f"{peer} - Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + f"{peer} - BGP session not established for the minimum required duration - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" ) # Check the TCP session message queues @@ -1452,23 +1449,22 @@ class VerifyBGPPeerSessionRibd(AntaTest): This test performs the following checks for each specified peer: 1. Verifies that the peer is found in its VRF in the BGP configuration. - 2. Checks that the BGP session is in the `Established` state. + 2. Verifies that the BGP session is `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. 3. Ensures that both input and output TCP message queues are empty. Can be disabled by setting `check_tcp_queues` global flag to `False`. - 4. Ensures that the peer remains established for the specified minimum duration, given by minimum_established_time (in seconds), globally. Expected Results ---------------- * Success: If all of the following conditions are met: - All specified peers are found in the BGP configuration. - - All peers sessions state are `Established`. + - All peers sessions state are `Established` and, if specified, has remained established for at least the duration given by `minimum_established_time`. - All peers have empty TCP message queues if `check_tcp_queues` is `True` (default). - All peers are established for specified minimum duration. * Failure: If any of the following occur: - A specified peer is not found in the BGP configuration. - - A peer's session state is not `Established`. + - A peer's session state is not `Established` or if specified, has not remained established for at least the duration specified by + the `minimum_established_time`. - A peer has non-empty TCP message queues (input or output) when `check_tcp_queues` is `True`. - - Any BGP session is not established for specified minimum duration. Examples -------- @@ -1496,8 +1492,8 @@ class VerifyBGPPeerSessionRibd(AntaTest): class Input(AntaTest.Input): """Input model for the VerifyBGPPeerSessionRibd test.""" - minimum_established_time: int | None = None - """Minimum established time(seconds) for all the neighbors.""" + minimum_established_time: PositiveInt | None = None + """Minimum established time (seconds) for all the BGP sessions.""" check_tcp_queues: bool = True """Flag to check if the TCP session queues are empty for all BGP peers. Defaults to `True`.""" bgp_peers: list[BgpPeer] @@ -1526,7 +1522,7 @@ def test(self) -> None: if self.inputs.minimum_established_time and (act_time := peer_data["establishedTime"]) < self.inputs.minimum_established_time: self.result.is_failure( - f"{peer} - Session is not established for expected time - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" + f"{peer} - BGP session not established for the minimum required duration - Expected: {self.inputs.minimum_established_time}s Actual: {act_time}s" ) # Check the TCP session message queues diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py index bbd142649..aae515c88 100644 --- a/tests/units/anta_tests/routing/test_bgp.py +++ b/tests/units/anta_tests/routing/test_bgp.py @@ -792,9 +792,11 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo "expected": { "result": "failure", "messages": [ - "AFI: evpn Peer: 10.100.0.13 - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "AFI: ipv4 SAFI: unicast VRF: DEV Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: evpn Peer: 10.100.0.13 - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - BGP session not established for the minimum required duration - " + "Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: DEV Peer: 10.100.0.12 - BGP session not established for the minimum required duration - " + "Expected: 10000s Actual: 9883s", ], }, }, @@ -1178,9 +1180,11 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo "expected": { "result": "failure", "messages": [ - "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "AFI: evpn Peer: 10.100.0.13 - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - BGP session not established for the minimum required duration - " + "Expected: 10000s Actual: 9883s", + "AFI: evpn Peer: 10.100.0.13 - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", + "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - BGP session not established for the minimum required duration - " + "Expected: 10000s Actual: 9883s", ], }, }, @@ -4627,8 +4631,8 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo "expected": { "result": "failure", "messages": [ - "Peer: 10.100.0.8 VRF: default - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "Peer: 10.100.0.9 VRF: MGMT - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.8 VRF: default - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.9 VRF: MGMT - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", ], }, }, @@ -5121,8 +5125,8 @@ def test_check_bgp_neighbor_capability(input_dict: dict[str, bool], expected: bo "expected": { "result": "failure", "messages": [ - "Peer: 10.100.0.8 VRF: default - Session is not established for expected time - Expected: 10000s Actual: 9883s", - "Peer: 10.100.0.9 VRF: MGMT - Session is not established for expected time - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.8 VRF: default - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", + "Peer: 10.100.0.9 VRF: MGMT - BGP session not established for the minimum required duration - Expected: 10000s Actual: 9883s", ], }, },