Skip to content

Commit

Permalink
Updated LLDP neighbor tes:1st round
Browse files Browse the repository at this point in the history
  • Loading branch information
VitthalMagadum committed Nov 6, 2024
1 parent ec31346 commit 71b4dea
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 111 deletions.
22 changes: 22 additions & 0 deletions anta/input_models/connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,25 @@ def __str__(self) -> str:
"""
df_status = ", df-bit: enabled" if self.df_bit else ""
return f"Host {self.destination} (src: {self.source}, vrf: {self.vrf}, size: {self.size}B, repeat: {self.repeat}{df_status})"


class Neighbor(BaseModel):
"""LLDP (Link Layer Discovery Protocol) model representing the port details and neighbor information."""

model_config = ConfigDict(extra="forbid")
port: Interface
"""The LLDP port for the local device."""
neighbor_device: str
"""The system name of the LLDP neighbor device."""
neighbor_port: Interface
"""The LLDP port on the neighboring device."""

def __str__(self) -> str:
"""Return a human-readable string representation of the Neighbor for reporting.
Examples
--------
Port Ethernet1 (Neighbor: DC1-SPINE2, Neighbor port: Ethernet2)
"""
return f"Port {self.port} (Neighbor: {self.neighbor_device}, Neighbor port: {self.neighbor_port})"
66 changes: 21 additions & 45 deletions anta/tests/connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@

from typing import ClassVar

from pydantic import BaseModel

from anta.custom_types import Interface
from anta.input_models.connectivity import Host
from anta.input_models.connectivity import Host, Neighbor
from anta.models import AntaCommand, AntaTemplate, AntaTest
from anta.tools import get_item, get_value


class VerifyReachability(AntaTest):
Expand Down Expand Up @@ -77,14 +75,19 @@ def test(self) -> None:


class VerifyLLDPNeighbors(AntaTest):
"""Verifies that the provided LLDP neighbors are present and connected with the correct configuration.
"""Verifies the connection status of the specified LLDP (Link Layer Discovery Protocol) neighbors.
This test performs the following checks for each specified LLDP neighbor:
1. Confirming matching ports on both local and neighboring devices.
2. Ensuring compatibility of device names and interface identifiers.
Expected Results
----------------
* Success: The test will pass if each of the provided LLDP neighbors is present and connected to the specified port and device.
* Success: The test will pass if all the provided LLDP neighbors are present and correctly connected to the specified port and device.
* Failure: The test will fail if any of the following conditions are met:
- The provided LLDP neighbor is not found.
- The system name or port of the LLDP neighbor does not match the provided information.
- The provided LLDP neighbor is not found in the LLDP table.
- The system name or port of the LLDP neighbor does not match the expected information.
Examples
--------
Expand All @@ -111,49 +114,22 @@ class Input(AntaTest.Input):
neighbors: list[Neighbor]
"""List of LLDP neighbors."""

class Neighbor(BaseModel):
"""Model for an LLDP neighbor."""

port: Interface
"""LLDP port."""
neighbor_device: str
"""LLDP neighbor device."""
neighbor_port: Interface
"""LLDP neighbor port."""

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifyLLDPNeighbors."""
failures: dict[str, list[str]] = {}
self.result.is_success()

output = self.instance_commands[0].json_output["lldpNeighbors"]

for neighbor in self.inputs.neighbors:
if neighbor.port not in output:
failures.setdefault("Port(s) not configured", []).append(neighbor.port)
if not (lldp_neighbor_info := get_value(output, f"{neighbor.port}.lldpNeighborInfo")) or not (
neighbor_info := get_item(lldp_neighbor_info, "systemName", neighbor.neighbor_device)
):
self.result.is_failure(f"{neighbor} - Not configured")
continue

if len(lldp_neighbor_info := output[neighbor.port]["lldpNeighborInfo"]) == 0:
failures.setdefault("No LLDP neighbor(s) on port(s)", []).append(neighbor.port)
continue
sytem_name = neighbor_info.get("systemName")
neighbor_port = neighbor_info.get("neighborInterfaceInfo", {}).get("interfaceId_v2")

if not any(
info["systemName"] == neighbor.neighbor_device and info["neighborInterfaceInfo"]["interfaceId_v2"] == neighbor.neighbor_port
for info in lldp_neighbor_info
):
neighbors = "\n ".join(
[
f"{neighbor[0]}_{neighbor[1]}"
for neighbor in [(info["systemName"], info["neighborInterfaceInfo"]["interfaceId_v2"]) for info in lldp_neighbor_info]
]
)
failures.setdefault("Wrong LLDP neighbor(s) on port(s)", []).append(f"{neighbor.port}\n {neighbors}")

if not failures:
self.result.is_success()
else:
failure_messages = []
for failure_type, ports in failures.items():
ports_str = "\n ".join(ports)
failure_messages.append(f"{failure_type}:\n {ports_str}")
self.result.is_failure("\n".join(failure_messages))
# Check if the neighbor details matches the expected details
if sytem_name != neighbor.neighbor_device or neighbor_port != neighbor.neighbor_port:
self.result.is_failure(f"{neighbor} - Inconsistent LLDP neighbors; Neighbor device: {sytem_name}, Neighbor port: {neighbor_port}")
106 changes: 40 additions & 66 deletions tests/units/anta_tests/test_connectivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,6 @@
{
"name": "success",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
Expand Down Expand Up @@ -256,16 +250,17 @@
},
},
],
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"expected": {"result": "success"},
},
{
"name": "success-multiple-neighbors",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
Expand Down Expand Up @@ -298,17 +293,16 @@
},
},
],
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"expected": {"result": "success"},
},
{
"name": "failure-port-not-configured",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
Expand All @@ -330,50 +324,17 @@
},
},
],
"expected": {"result": "failure", "messages": ["Port(s) not configured:\n Ethernet2"]},
},
{
"name": "failure-no-neighbor",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
"Ethernet1": {
"lldpNeighborInfo": [
{
"chassisIdType": "macAddress",
"chassisId": "001c.73a0.fc18",
"systemName": "DC1-SPINE1",
"neighborInterfaceInfo": {
"interfaceIdType": "interfaceName",
"interfaceId": '"Ethernet1"',
"interfaceId_v2": "Ethernet1",
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
},
},
],
},
"Ethernet2": {"lldpNeighborInfo": []},
},
},
],
"expected": {"result": "failure", "messages": ["No LLDP neighbor(s) on port(s):\n Ethernet2"]},
"expected": {"result": "failure", "messages": ["Port Ethernet2 (Neighbor: DC1-SPINE2, Neighbor port: Ethernet1) - Not configured"]},
},
{
"name": "failure-wrong-neighbor",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
Expand Down Expand Up @@ -410,18 +371,23 @@
},
},
],
"expected": {"result": "failure", "messages": ["Wrong LLDP neighbor(s) on port(s):\n Ethernet2\n DC1-SPINE2_Ethernet2"]},
},
{
"name": "failure-multiple",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
{"port": "Ethernet3", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
],
},
"expected": {
"result": "failure",
"messages": [
"Port Ethernet2 (Neighbor: DC1-SPINE2, Neighbor port: Ethernet1) - "
"Inconsistent LLDP neighbors; Neighbor device: DC1-SPINE2, Neighbor port: Ethernet2"
],
},
},
{
"name": "failure-multiple",
"test": VerifyLLDPNeighbors,
"eos_data": [
{
"lldpNeighbors": {
Expand All @@ -444,23 +410,26 @@
},
},
],
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
{"port": "Ethernet3", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
],
},
"expected": {
"result": "failure",
"messages": [
"Wrong LLDP neighbor(s) on port(s):\n Ethernet1\n DC1-SPINE1_Ethernet2\n"
"No LLDP neighbor(s) on port(s):\n Ethernet2\n"
"Port(s) not configured:\n Ethernet3"
"Port Ethernet1 (Neighbor: DC1-SPINE1, Neighbor port: Ethernet1) - Inconsistent LLDP neighbors; "
"Neighbor device: DC1-SPINE1, Neighbor port: Ethernet2",
"Port Ethernet2 (Neighbor: DC1-SPINE2, Neighbor port: Ethernet1) - Not configured",
"Port Ethernet3 (Neighbor: DC1-SPINE3, Neighbor port: Ethernet1) - Not configured",
],
},
},
{
"name": "failure-multiple-neighbors",
"test": VerifyLLDPNeighbors,
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
],
},
"eos_data": [
{
"lldpNeighbors": {
Expand Down Expand Up @@ -493,6 +462,11 @@
},
},
],
"expected": {"result": "failure", "messages": ["Wrong LLDP neighbor(s) on port(s):\n Ethernet1\n DC1-SPINE1_Ethernet1\n DC1-SPINE2_Ethernet1"]},
"inputs": {
"neighbors": [
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
],
},
"expected": {"result": "failure", "messages": ["Port Ethernet1 (Neighbor: DC1-SPINE3, Neighbor port: Ethernet1) - Not configured"]},
},
]

0 comments on commit 71b4dea

Please sign in to comment.