Skip to content

ANTA catalog for Adaptive Virtual Topology (AVT) tests

Tests

VerifyAVTPathHealth

Verifies the status of all Adaptive Virtual Topology (AVT) paths for all VRFs.

Expected Results
  • Success: The test will pass if all AVT paths for all VRFs are active and valid.
  • Failure: The test will fail if the AVT path is not configured or if any AVT path under any VRF is either inactive or invalid.
Examples
anta.tests.avt:
  - VerifyAVTPathHealth:
Source code in anta/tests/avt.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
class VerifyAVTPathHealth(AntaTest):
    """Verifies the status of all Adaptive Virtual Topology (AVT) paths for all VRFs.

    Expected Results
    ----------------
    * Success: The test will pass if all AVT paths for all VRFs are active and valid.
    * Failure: The test will fail if the AVT path is not configured or if any AVT path under any VRF is either inactive or invalid.

    Examples
    --------
    ```yaml
    anta.tests.avt:
      - VerifyAVTPathHealth:
    ```
    """

    description = "Verifies the status of all AVT paths for all VRFs."
    categories: ClassVar[list[str]] = ["avt"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show adaptive-virtual-topology path")]

    @skip_on_platforms(["cEOSLab", "vEOS-lab"])
    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifyAVTPathHealth."""
        # Initialize the test result as success
        self.result.is_success()

        # Get the command output
        command_output = self.instance_commands[0].json_output.get("vrfs", {})

        # Check if AVT is configured
        if not command_output:
            self.result.is_failure("Adaptive virtual topology paths are not configured.")
            return

        # Iterate over each VRF
        for vrf, vrf_data in command_output.items():
            # Iterate over each AVT path
            for profile, avt_path in vrf_data.get("avts", {}).items():
                for path, flags in avt_path.get("avtPaths", {}).items():
                    # Get the status of the AVT path
                    valid = flags["flags"]["valid"]
                    active = flags["flags"]["active"]

                    # Check the status of the AVT path
                    if not valid and not active:
                        self.result.is_failure(f"AVT path {path} for profile {profile} in VRF {vrf} is invalid and not active.")
                    elif not valid:
                        self.result.is_failure(f"AVT path {path} for profile {profile} in VRF {vrf} is invalid.")
                    elif not active:
                        self.result.is_failure(f"AVT path {path} for profile {profile} in VRF {vrf} is not active.")

VerifyAVTRole

Verifies the Adaptive Virtual Topology (AVT) role of a device.

Expected Results
  • Success: The test will pass if the AVT role of the device matches the expected role.
  • Failure: The test will fail if the AVT is not configured or if the AVT role does not match the expected role.
Examples
anta.tests.avt:
  - VerifyAVTRole:
      role: edge

Inputs

Name Type Description Default
role str
Expected AVT role of the device.
-
Source code in anta/tests/avt.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
class VerifyAVTRole(AntaTest):
    """Verifies the Adaptive Virtual Topology (AVT) role of a device.

    Expected Results
    ----------------
    * Success: The test will pass if the AVT role of the device matches the expected role.
    * Failure: The test will fail if the AVT is not configured or if the AVT role does not match the expected role.

    Examples
    --------
    ```yaml
    anta.tests.avt:
      - VerifyAVTRole:
          role: edge
    ```
    """

    description = "Verifies the AVT role of a device."
    categories: ClassVar[list[str]] = ["avt"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show adaptive-virtual-topology path")]

    class Input(AntaTest.Input):
        """Input model for the VerifyAVTRole test."""

        role: str
        """Expected AVT role of the device."""

    @skip_on_platforms(["cEOSLab", "vEOS-lab"])
    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifyAVTRole."""
        # Initialize the test result as success
        self.result.is_success()

        # Get the command output
        command_output = self.instance_commands[0].json_output

        # Check if the AVT role matches the expected role
        if self.inputs.role != command_output.get("role"):
            self.result.is_failure(f"Expected AVT role as `{self.inputs.role}`, but found `{command_output.get('role')}` instead.")

VerifyAVTSpecificPath

Verifies the Adaptive Virtual Topology (AVT) path.

This test performs the following checks for each specified LLDP neighbor:

  1. Confirming that the AVT paths are associated with the specified VRF.
  2. Verifying that each AVT path is active and valid.
  3. Ensuring that the AVT path matches the specified type (direct/multihop) if provided.
Expected Results
  • Success: The test will pass if all of the following conditions are met:
    • All AVT paths for the specified VRF are active, valid, and match the specified path type (direct/multihop), if provided.
    • If multiple paths are configured, the test will pass only if all paths meet these criteria.
  • Failure: The test will fail if any of the following conditions are met:
    • No AVT paths are configured for the specified VRF.
    • Any configured path is inactive, invalid, or does not match the specified type.
Examples
anta.tests.avt:
  - VerifyAVTSpecificPath:
      avt_paths:
        - avt_name: CONTROL-PLANE-PROFILE
          vrf: default
          destination: 10.101.255.2
          next_hop: 10.101.255.1
          path_type: direct

Inputs

Name Type Description Default
avt_paths list[AVTPath]
List of AVT paths to verify.
-
AVTPaths type[AVTPath]
To maintain backward compatibility.
AVTPath
Source code in anta/tests/avt.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
class VerifyAVTSpecificPath(AntaTest):
    """Verifies the Adaptive Virtual Topology (AVT) path.

    This test performs the following checks for each specified LLDP neighbor:

      1. Confirming that the AVT paths are associated with the specified VRF.
      2. Verifying that each AVT path is active and valid.
      3. Ensuring that the AVT path matches the specified type (direct/multihop) if provided.

    Expected Results
    ----------------
    * Success: The test will pass if all of the following conditions are met:
        - All AVT paths for the specified VRF are active, valid, and match the specified path type (direct/multihop), if provided.
        - If multiple paths are configured, the test will pass only if all paths meet these criteria.
    * Failure: The test will fail if any of the following conditions are met:
        - No AVT paths are configured for the specified VRF.
        - Any configured path is inactive, invalid, or does not match the specified type.

    Examples
    --------
    ```yaml
    anta.tests.avt:
      - VerifyAVTSpecificPath:
          avt_paths:
            - avt_name: CONTROL-PLANE-PROFILE
              vrf: default
              destination: 10.101.255.2
              next_hop: 10.101.255.1
              path_type: direct
    ```
    """

    categories: ClassVar[list[str]] = ["avt"]
    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show adaptive-virtual-topology path", revision=1)]

    class Input(AntaTest.Input):
        """Input model for the VerifyAVTSpecificPath test."""

        avt_paths: list[AVTPath]
        """List of AVT paths to verify."""
        AVTPaths: ClassVar[type[AVTPath]] = AVTPath
        """To maintain backward compatibility."""

    @skip_on_platforms(["cEOSLab", "vEOS-lab"])
    @AntaTest.anta_test
    def test(self) -> None:
        """Main test function for VerifyAVTSpecificPath."""
        # Assume the test is successful until a failure is detected
        self.result.is_success()

        command_output = self.instance_commands[0].json_output
        for avt_path in self.inputs.avt_paths:
            if (path_output := get_value(command_output, f"vrfs.{avt_path.vrf}.avts.{avt_path.avt_name}.avtPaths")) is None:
                self.result.is_failure(f"{avt_path} - No AVT path configured")
                return

            path_found = path_type_found = False

            # Check each AVT path
            for path, path_data in path_output.items():
                dest = path_data.get("destination")
                nexthop = path_data.get("nexthopAddr")
                path_type = "direct" if get_value(path_data, "flags.directPath") else "multihop"

                if not avt_path.path_type:
                    path_found = all([dest == str(avt_path.destination), nexthop == str(avt_path.next_hop)])

                else:
                    path_type_found = all([dest == str(avt_path.destination), nexthop == str(avt_path.next_hop), path_type == avt_path.path_type])
                    if path_type_found:
                        path_found = True
                        # Check the path status and type against the expected values
                        valid = get_value(path_data, "flags.valid")
                        active = get_value(path_data, "flags.active")
                        if not all([valid, active]):
                            self.result.is_failure(f"{avt_path} - Incorrect path {path} - Valid: {valid}, Active: {active}")

            # If no matching path found, mark the test as failed
            if not path_found:
                if avt_path.path_type and not path_type_found:
                    self.result.is_failure(f"{avt_path} Path Type: {avt_path.path_type} - Path not found")
                else:
                    self.result.is_failure(f"{avt_path} - Path not found")

Input models

AVTPath

AVT (Adaptive Virtual Topology) model representing path details and associated information.

Name Type Description Default
vrf str
VRF context. Defaults to `default`.
'default'
avt_name str
The name of the Adaptive Virtual Topology (AVT).
-
destination IPv4Address
The IPv4 address of the destination peer in the AVT.
-
next_hop IPv4Address
The IPv4 address of the next hop used to reach the AVT peer.
-
path_type str | None
Specifies the type of path for the AVT. If not specified, both types 'direct' and 'multihop' are considered.
None
Source code in anta/input_models/avt.py
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class AVTPath(BaseModel):
    """AVT (Adaptive Virtual Topology) model representing path details and associated information."""

    model_config = ConfigDict(extra="forbid")
    vrf: str = "default"
    """VRF context. Defaults to `default`."""
    avt_name: str
    """The name of the Adaptive Virtual Topology (AVT)."""
    destination: IPv4Address
    """The IPv4 address of the destination peer in the AVT."""
    next_hop: IPv4Address
    """The IPv4 address of the next hop used to reach the AVT peer."""
    path_type: str | None = None
    """Specifies the type of path for the AVT. If not specified, both types 'direct' and 'multihop' are considered."""

    def __str__(self) -> str:
        """Return a human-readable string representation of the AVTPath for reporting.

        Examples
        --------
        AVT CONTROL-PLANE-PROFILE VRF: default (Destination: 10.101.255.2, Next-hop: 10.101.255.1)

        """
        return f"AVT {self.avt_name} VRF: {self.vrf} (Destination: {self.destination}, Next-hop: {self.next_hop})"