-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
102 changed files
with
2,634 additions
and
2,371 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Package related to all ANTA tests input models.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Module containing input models for BFD tests.""" | ||
|
||
from __future__ import annotations | ||
|
||
from ipaddress import IPv4Address | ||
|
||
from pydantic import BaseModel, ConfigDict | ||
|
||
from anta.custom_types import BfdInterval, BfdMultiplier, BfdProtocol | ||
|
||
|
||
class BFDPeer(BaseModel): | ||
"""BFD (Bidirectional Forwarding Detection) model representing the peer details. | ||
Only IPv4 peers are supported for now. | ||
""" | ||
|
||
model_config = ConfigDict(extra="forbid") | ||
peer_address: IPv4Address | ||
"""IPv4 address of a BFD peer.""" | ||
vrf: str = "default" | ||
"""Optional VRF for the BFD peer. Defaults to `default`.""" | ||
tx_interval: BfdInterval | None = None | ||
"""Tx interval of BFD peer in milliseconds. Required field in the `VerifyBFDPeersIntervals` test.""" | ||
rx_interval: BfdInterval | None = None | ||
"""Rx interval of BFD peer in milliseconds. Required field in the `VerifyBFDPeersIntervals` test.""" | ||
multiplier: BfdMultiplier | None = None | ||
"""Multiplier of BFD peer. Required field in the `VerifyBFDPeersIntervals` test.""" | ||
protocols: list[BfdProtocol] | None = None | ||
"""List of protocols to be verified. Required field in the `VerifyBFDPeersRegProtocols` test.""" | ||
|
||
def __str__(self) -> str: | ||
"""Return a human-readable string representation of the BFDPeer for reporting.""" | ||
return f"Peer: {self.peer_address} VRF: {self.vrf}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Module containing input models for connectivity tests.""" | ||
|
||
from __future__ import annotations | ||
|
||
from ipaddress import IPv4Address | ||
from typing import Any | ||
from warnings import warn | ||
|
||
from pydantic import BaseModel, ConfigDict | ||
|
||
from anta.custom_types import Interface | ||
|
||
|
||
class Host(BaseModel): | ||
"""Model for a remote host to ping.""" | ||
|
||
model_config = ConfigDict(extra="forbid") | ||
destination: IPv4Address | ||
"""IPv4 address to ping.""" | ||
source: IPv4Address | Interface | ||
"""IPv4 address source IP or egress interface to use.""" | ||
vrf: str = "default" | ||
"""VRF context. Defaults to `default`.""" | ||
repeat: int = 2 | ||
"""Number of ping repetition. Defaults to 2.""" | ||
size: int = 100 | ||
"""Specify datagram size. Defaults to 100.""" | ||
df_bit: bool = False | ||
"""Enable do not fragment bit in IP header. Defaults to False.""" | ||
|
||
def __str__(self) -> str: | ||
"""Return a human-readable string representation of the Host for reporting. | ||
Examples | ||
-------- | ||
Host 10.1.1.1 (src: 10.2.2.2, vrf: mgmt, size: 100B, repeat: 2) | ||
""" | ||
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 LLDPNeighbor(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 LLDPNeighbor 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})" | ||
|
||
|
||
class Neighbor(LLDPNeighbor): # pragma: no cover | ||
"""Alias for the LLDPNeighbor model to maintain backward compatibility. | ||
When initialized, it will emit a deprecation warning and call the LLDPNeighbor model. | ||
TODO: Remove this class in ANTA v2.0.0. | ||
""" | ||
|
||
def __init__(self, **data: Any) -> None: # noqa: ANN401 | ||
"""Initialize the LLDPNeighbor class, emitting a depreciation warning.""" | ||
warn( | ||
message="Neighbor model is deprecated and will be removed in ANTA v2.0.0. Use the LLDPNeighbor model instead.", | ||
category=DeprecationWarning, | ||
stacklevel=2, | ||
) | ||
super().__init__(**data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Module containing input models for interface tests.""" | ||
|
||
from __future__ import annotations | ||
|
||
from typing import Literal | ||
|
||
from pydantic import BaseModel | ||
|
||
from anta.custom_types import Interface | ||
|
||
|
||
class InterfaceState(BaseModel): | ||
"""Model for an interface state.""" | ||
|
||
name: Interface | ||
"""Interface to validate.""" | ||
status: Literal["up", "down", "adminDown"] | ||
"""Expected status of the interface.""" | ||
line_protocol_status: Literal["up", "down", "testing", "unknown", "dormant", "notPresent", "lowerLayerDown"] | None = None | ||
"""Expected line protocol status of the interface.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Package related to routing tests input models.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# Copyright (c) 2023-2024 Arista Networks, Inc. | ||
# Use of this source code is governed by the Apache License 2.0 | ||
# that can be found in the LICENSE file. | ||
"""Module containing input models for routing BGP tests.""" | ||
|
||
from __future__ import annotations | ||
|
||
from ipaddress import IPv4Address, IPv6Address | ||
from typing import TYPE_CHECKING, Any | ||
from warnings import warn | ||
|
||
from pydantic import BaseModel, ConfigDict, PositiveInt, model_validator | ||
|
||
from anta.custom_types import Afi, Safi | ||
|
||
if TYPE_CHECKING: | ||
import sys | ||
|
||
if sys.version_info >= (3, 11): | ||
from typing import Self | ||
else: | ||
from typing_extensions import Self | ||
|
||
AFI_SAFI_EOS_KEY = { | ||
("ipv4", "unicast"): "ipv4Unicast", | ||
("ipv4", "multicast"): "ipv4Multicast", | ||
("ipv4", "labeled-unicast"): "ipv4MplsLabels", | ||
("ipv4", "sr-te"): "ipv4SrTe", | ||
("ipv6", "unicast"): "ipv6Unicast", | ||
("ipv6", "multicast"): "ipv6Multicast", | ||
("ipv6", "labeled-unicast"): "ipv6MplsLabels", | ||
("ipv6", "sr-te"): "ipv6SrTe", | ||
("vpn-ipv4", None): "ipv4MplsVpn", | ||
("vpn-ipv6", None): "ipv6MplsVpn", | ||
("evpn", None): "l2VpnEvpn", | ||
("rt-membership", None): "rtMembership", | ||
("path-selection", None): "dps", | ||
("link-state", None): "linkState", | ||
} | ||
"""Dictionary mapping AFI/SAFI to EOS key representation.""" | ||
|
||
|
||
class BgpAddressFamily(BaseModel): | ||
"""Model for a BGP address family.""" | ||
|
||
model_config = ConfigDict(extra="forbid") | ||
afi: Afi | ||
"""BGP Address Family Identifier (AFI).""" | ||
safi: Safi | None = None | ||
"""BGP Subsequent Address Family Identifier (SAFI). Required when `afi` is `ipv4` or `ipv6`.""" | ||
vrf: str = "default" | ||
"""Optional VRF when `afi` is `ipv4` or `ipv6`. Defaults to `default`. | ||
If the input `afi` is NOT `ipv4` or `ipv6` (e.g. `evpn`, `vpn-ipv4`, etc.), the `vrf` must be `default`. | ||
These AFIs operate at a global level and do not use the VRF concept in the same way as IPv4/IPv6. | ||
""" | ||
num_peers: PositiveInt | None = None | ||
"""Number of expected established BGP peers with negotiated AFI/SAFI. Required field in the `VerifyBGPPeerCount` test.""" | ||
peers: list[IPv4Address | IPv6Address] | None = None | ||
"""List of expected IPv4/IPv6 BGP peers supporting the AFI/SAFI. Required field in the `VerifyBGPSpecificPeers` test.""" | ||
check_tcp_queues: bool = True | ||
"""Flag to check if the TCP session queues are empty for a BGP peer. Defaults to `True`. | ||
Can be disabled in the `VerifyBGPPeersHealth` and `VerifyBGPSpecificPeers` tests. | ||
""" | ||
check_peer_state: bool = False | ||
"""Flag to check if the peers are established with negotiated AFI/SAFI. Defaults to `False`. | ||
Can be enabled in the `VerifyBGPPeerCount` tests. | ||
""" | ||
|
||
@model_validator(mode="after") | ||
def validate_inputs(self) -> Self: | ||
"""Validate the inputs provided to the BgpAddressFamily class. | ||
If `afi` is either `ipv4` or `ipv6`, `safi` must be provided. | ||
If `afi` is not `ipv4` or `ipv6`, `safi` must NOT be provided and `vrf` must be `default`. | ||
""" | ||
if self.afi in ["ipv4", "ipv6"]: | ||
if self.safi is None: | ||
msg = "'safi' must be provided when afi is ipv4 or ipv6" | ||
raise ValueError(msg) | ||
elif self.safi is not None: | ||
msg = "'safi' must not be provided when afi is not ipv4 or ipv6" | ||
raise ValueError(msg) | ||
elif self.vrf != "default": | ||
msg = "'vrf' must be default when afi is not ipv4 or ipv6" | ||
raise ValueError(msg) | ||
return self | ||
|
||
@property | ||
def eos_key(self) -> str: | ||
"""AFI/SAFI EOS key representation.""" | ||
# Pydantic handles the validation of the AFI/SAFI combination, so we can ignore error handling here. | ||
return AFI_SAFI_EOS_KEY[(self.afi, self.safi)] | ||
|
||
def __str__(self) -> str: | ||
"""Return a string representation of the BgpAddressFamily model. Used in failure messages. | ||
Examples | ||
-------- | ||
- AFI:ipv4 SAFI:unicast VRF:default | ||
- AFI:evpn | ||
""" | ||
base_string = f"AFI: {self.afi}" | ||
if self.safi is not None: | ||
base_string += f" SAFI: {self.safi}" | ||
if self.afi in ["ipv4", "ipv6"]: | ||
base_string += f" VRF: {self.vrf}" | ||
return base_string | ||
|
||
|
||
class BgpAfi(BgpAddressFamily): # pragma: no cover | ||
"""Alias for the BgpAddressFamily model to maintain backward compatibility. | ||
When initialized, it will emit a deprecation warning and call the BgpAddressFamily model. | ||
TODO: Remove this class in ANTA v2.0.0. | ||
""" | ||
|
||
def __init__(self, **data: Any) -> None: # noqa: ANN401 | ||
"""Initialize the BgpAfi class, emitting a deprecation warning.""" | ||
warn( | ||
message="BgpAfi model is deprecated and will be removed in ANTA v2.0.0. Use the BgpAddressFamily model instead.", | ||
category=DeprecationWarning, | ||
stacklevel=2, | ||
) | ||
super().__init__(**data) |
Oops, something went wrong.