Skip to content

Commit

Permalink
feat(anta): Added the test case to verify SNMP Logging Configuration (#…
Browse files Browse the repository at this point in the history
…849)

* issue_821 Added TC for SNMP logging

* Issue_821: Refactored testcase with latest changes of input modules and updated TC, docstrings

* Issue_821: Updated docstrings and test class, variable names

* Minor updates

---------

Co-authored-by: VitthalMagadum <yvitthal.magadum-ext@arista.com>
Co-authored-by: Geetanjali.mane <geetanjali.mane-ext@arista.com>
Co-authored-by: Carl Baillargeon <carl.baillargeon@arista.com>
  • Loading branch information
4 people authored Jan 14, 2025
1 parent c91193e commit 509c3cf
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 2 deletions.
23 changes: 22 additions & 1 deletion anta/input_models/snmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,30 @@

from __future__ import annotations

from ipaddress import IPv4Address

from pydantic import BaseModel, ConfigDict

from anta.custom_types import SnmpEncryptionAlgorithm, SnmpHashingAlgorithm, SnmpVersion
from anta.custom_types import Hostname, SnmpEncryptionAlgorithm, SnmpHashingAlgorithm, SnmpVersion


class SnmpHost(BaseModel):
"""Model for a SNMP host."""

model_config = ConfigDict(extra="forbid")
hostname: IPv4Address | Hostname
"""IPv4 address or hostname of the SNMP notification host."""
vrf: str = "default"
"""Optional VRF for SNMP hosts. If not provided, it defaults to `default`."""

def __str__(self) -> str:
"""Return a human-readable string representation of the SnmpHost for reporting.
Examples
--------
- Host: 192.168.1.100 VRF: default
"""
return f"Host: {self.hostname} VRF: {self.vrf}"


class SnmpUser(BaseModel):
Expand Down
73 changes: 72 additions & 1 deletion anta/tests/snmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pydantic import field_validator

from anta.custom_types import PositiveInteger, SnmpErrorCounter, SnmpPdu
from anta.input_models.snmp import SnmpUser
from anta.input_models.snmp import SnmpHost, SnmpUser
from anta.models import AntaCommand, AntaTest
from anta.tools import get_value

Expand Down Expand Up @@ -344,6 +344,77 @@ def test(self) -> None:
self.result.is_failure(f"The following SNMP error counters are not found or have non-zero error counters:\n{error_counters_not_ok}")


class VerifySnmpHostLogging(AntaTest):
"""Verifies SNMP logging configurations.
This test performs the following checks:
1. SNMP logging is enabled globally.
2. For each specified SNMP host:
- Host exists in configuration.
- Host's VRF assignment matches expected value.
Expected Results
----------------
* Success: The test will pass if all of the following conditions are met:
- SNMP logging is enabled on the device.
- All specified hosts are configured with correct VRF assignments.
* Failure: The test will fail if any of the following conditions is met:
- SNMP logging is disabled on the device.
- SNMP host not found in configuration.
- Host's VRF assignment doesn't match expected value.
Examples
--------
```yaml
anta.tests.snmp:
- VerifySnmpHostLogging:
hosts:
- hostname: 192.168.1.100
vrf: default
- hostname: 192.168.1.103
vrf: MGMT
```
"""

categories: ClassVar[list[str]] = ["snmp"]
commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)]

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

hosts: list[SnmpHost]
"""List of SNMP hosts."""

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifySnmpHostLogging."""
self.result.is_success()

command_output = self.instance_commands[0].json_output.get("logging", {})
# If SNMP logging is disabled, test fails.
if not command_output.get("loggingEnabled"):
self.result.is_failure("SNMP logging is disabled")
return

host_details = command_output.get("hosts", {})

for host in self.inputs.hosts:
hostname = str(host.hostname)
vrf = host.vrf
actual_snmp_host = host_details.get(hostname, {})

# If SNMP host is not configured on the device, test fails.
if not actual_snmp_host:
self.result.is_failure(f"{host} - Not configured")
continue

# If VRF is not matches the expected value, test fails.
actual_vrf = "default" if (vrf_name := actual_snmp_host.get("vrf")) == "" else vrf_name
if actual_vrf != vrf:
self.result.is_failure(f"{host} - Incorrect VRF - Actual: {actual_vrf}")


class VerifySnmpUser(AntaTest):
"""Verifies the SNMP user configurations.
Expand Down
7 changes: 7 additions & 0 deletions examples/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,13 @@ anta.tests.snmp:
# Verifies the SNMP error counters.
error_counters:
- inVersionErrs
- VerifySnmpHostLogging:
# Verifies SNMP logging configurations.
hosts:
- hostname: 192.168.1.100
vrf: default
- hostname: 192.168.1.103
vrf: MGMT
- VerifySnmpIPv4Acl:
# Verifies if the SNMP agent has IPv4 ACL(s) configured.
number: 3
Expand Down
52 changes: 52 additions & 0 deletions tests/units/anta_tests/test_snmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from anta.tests.snmp import (
VerifySnmpContact,
VerifySnmpErrorCounters,
VerifySnmpHostLogging,
VerifySnmpIPv4Acl,
VerifySnmpIPv6Acl,
VerifySnmpLocation,
Expand Down Expand Up @@ -320,6 +321,57 @@
],
},
},
{
"name": "success",
"test": VerifySnmpHostLogging,
"eos_data": [
{
"logging": {
"loggingEnabled": True,
"hosts": {
"192.168.1.100": {"port": 162, "vrf": ""},
"192.168.1.101": {"port": 162, "vrf": "MGMT"},
"snmp-server-01": {"port": 162, "vrf": "default"},
},
}
}
],
"inputs": {
"hosts": [
{"hostname": "192.168.1.100", "vrf": "default"},
{"hostname": "192.168.1.101", "vrf": "MGMT"},
{"hostname": "snmp-server-01", "vrf": "default"},
]
},
"expected": {"result": "success"},
},
{
"name": "failure-logging-disabled",
"test": VerifySnmpHostLogging,
"eos_data": [{"logging": {"loggingEnabled": False}}],
"inputs": {"hosts": [{"hostname": "192.168.1.100", "vrf": "default"}, {"hostname": "192.168.1.101", "vrf": "MGMT"}]},
"expected": {"result": "failure", "messages": ["SNMP logging is disabled"]},
},
{
"name": "failure-mismatch-vrf",
"test": VerifySnmpHostLogging,
"eos_data": [{"logging": {"loggingEnabled": True, "hosts": {"192.168.1.100": {"port": 162, "vrf": "MGMT"}, "192.168.1.101": {"port": 162, "vrf": "Test"}}}}],
"inputs": {"hosts": [{"hostname": "192.168.1.100", "vrf": "default"}, {"hostname": "192.168.1.101", "vrf": "MGMT"}]},
"expected": {
"result": "failure",
"messages": ["Host: 192.168.1.100 VRF: default - Incorrect VRF - Actual: MGMT", "Host: 192.168.1.101 VRF: MGMT - Incorrect VRF - Actual: Test"],
},
},
{
"name": "failure-host-not-configured",
"test": VerifySnmpHostLogging,
"eos_data": [{"logging": {"loggingEnabled": True, "hosts": {"192.168.1.100": {"port": 162, "vrf": "MGMT"}, "192.168.1.103": {"port": 162, "vrf": "Test"}}}}],
"inputs": {"hosts": [{"hostname": "192.168.1.101", "vrf": "default"}, {"hostname": "192.168.1.102", "vrf": "MGMT"}]},
"expected": {
"result": "failure",
"messages": ["Host: 192.168.1.101 VRF: default - Not configured", "Host: 192.168.1.102 VRF: MGMT - Not configured"],
},
},
{
"name": "success",
"test": VerifySnmpUser,
Expand Down

0 comments on commit 509c3cf

Please sign in to comment.