feat: declare the SNMP health OIDs instead of collecting them (0.3.0) #14

Merged
christianmanivong merged 1 commits from feat/snmp-health-profile into master 2026-10-16 23:06:58 +00:00
3 changed files with 48 additions and 64 deletions

No files matched your search

+14 -63
View File
@@ -19,7 +19,7 @@ Netmiko device type: ``hp_procurve`` / ``hp_procurve_telnet``
import logging import logging
import re import re
import socket import socket
from typing import Any, Dict, List, Optional, Union from typing import Any, ClassVar, Dict, List, Optional, Union
import netaddr import netaddr
from netmiko import ConnectHandler from netmiko import ConnectHandler
@@ -104,6 +104,19 @@ class ProcurveDriver(ConfigLifecycleMixin, SwitchDriver):
NETMIKO_DEVICE_TYPE = "hp_procurve" NETMIKO_DEVICE_TYPE = "hp_procurve"
NETMIKO_DEVICE_TYPE_TELNET = "hp_procurve_telnet" NETMIKO_DEVICE_TYPE_TELNET = "hp_procurve_telnet"
#: Where the switch publishes its health values over SNMP
#: (napalm-device-types ``SnmpHealthProfile``); the application polls.
#: Memory is NETSWITCH-MIB ``hpLocalMemEntry``: .5 total, .6 free, .7 allocated.
SNMP_HEALTH_PROFILE: ClassVar[Dict[str, Any]] = {
"uptime": {"oids": ["1.3.6.1.4.1.11.2.14.11.1.2.4.1.5.1"]},
"cpu": {"oids": ["1.3.6.1.4.1.11.2.14.11.5.1.9.6.1.0", "1.3.6.1.4.1.11.2.3.7.8.6.1.0"]},
"memory": {
"total": {"oids": ["1.3.6.1.4.1.11.2.14.11.5.1.1.2.1.1.1.5.1"]},
"free": {"oids": ["1.3.6.1.4.1.11.2.14.11.5.1.1.2.1.1.1.6.1"]},
"unit": "bytes",
},
}
def __init__( def __init__(
self, self,
hostname: str, hostname: str,
@@ -1295,68 +1308,6 @@ class ProcurveDriver(ConfigLifecycleMixin, SwitchDriver):
else f"[warn] Verification — community not found: {out[:200]}") else f"[warn] Verification — community not found: {out[:200]}")
return {"success": success, "output": "\n".join(lines)} return {"success": success, "output": "\n".join(lines)}
# ------------------------------------------------------------------
# Health metrics (SNMP)
# ------------------------------------------------------------------
@classmethod
async def get_health_metrics(cls, snmp_get, snmp_walk) -> dict:
import asyncio
from napalm_device_types._ucd_metrics import build_if_metrics, ticks_to_seconds
_HP_CPU_STAT = "1.3.6.1.4.1.11.2.14.11.5.1.9.6.1.0"
_HP_CPU_STAT_OLD = "1.3.6.1.4.1.11.2.3.7.8.6.1.0"
_HP_MEM_TOTAL = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.1.1.1.5.1"
_HP_MEM_USED = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.1.1.1.6.1"
_HP_UPTIME = "1.3.6.1.4.1.11.2.14.11.1.2.4.1.5.1"
_OID_IF_DESCR = "1.3.6.1.2.1.2.2.1.2"
_OID_IF_SPEED = "1.3.6.1.2.1.2.2.1.5"
_OID_IF_IN_OCT = "1.3.6.1.2.1.2.2.1.10"
_OID_IF_OUT_OCT = "1.3.6.1.2.1.2.2.1.16"
_OID_IF_IN_ERR = "1.3.6.1.2.1.2.2.1.14"
_OID_IF_OUT_ERR = "1.3.6.1.2.1.2.2.1.20"
(hp_uptime, cpu_raw, cpu_old, mem_t, mem_u,
descr, speed, in_oct, out_oct, in_err, out_err) = await asyncio.gather(
snmp_get(_HP_UPTIME),
snmp_get(_HP_CPU_STAT),
snmp_get(_HP_CPU_STAT_OLD),
snmp_get(_HP_MEM_TOTAL),
snmp_get(_HP_MEM_USED),
snmp_walk(_OID_IF_DESCR),
snmp_walk(_OID_IF_SPEED),
snmp_walk(_OID_IF_IN_OCT),
snmp_walk(_OID_IF_OUT_OCT),
snmp_walk(_OID_IF_IN_ERR),
snmp_walk(_OID_IF_OUT_ERR),
)
metrics: dict = {}
secs = ticks_to_seconds(hp_uptime)
if secs is not None:
metrics["uptime_seconds"] = secs
cpu = cpu_raw or cpu_old
if cpu is not None:
try:
metrics["cpu_percent"] = float(cpu)
except ValueError:
pass
if mem_t and mem_u:
try:
total = int(mem_t)
used = int(mem_u)
metrics["memory_total_bytes"] = total
metrics["memory_used_bytes"] = used
metrics["memory_percent"] = round(used / total * 100, 1) if total else 0.0
except ValueError:
pass
build_if_metrics(metrics, descr, speed, in_oct, out_oct, in_err, out_err)
return metrics
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Helpers # Helpers
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "napalm-hpe-aruba-procurve" name = "napalm-hpe-aruba-procurve"
version = "0.2.0" version = "0.3.0"
description = "NAPALM driver for HPE/Aruba ProCurve switches with auto-detecting transport (REST API, SSH, legacy SSH, Telnet)" description = "NAPALM driver for HPE/Aruba ProCurve switches with auto-detecting transport (REST API, SSH, legacy SSH, Telnet)"
readme = "README.md" readme = "README.md"
license = { text = "Apache-2.0" } license = { text = "Apache-2.0" }
+33
View File
@@ -0,0 +1,33 @@
"""The switch's SNMP health OIDs, declared as data (napalm-device-types docs/STRUCTURE.md).
The driver does not collect over SNMP; the application polls with this profile.
"""
from napalm_procurve.procurve import ProcurveDriver
PROFILE = ProcurveDriver.SNMP_HEALTH_PROFILE
MEM = "1.3.6.1.4.1.11.2.14.11.5.1.1.2.1.1.1" # NETSWITCH-MIB hpLocalMemEntry
def test_the_driver_does_not_collect_itself():
assert "get_health_metrics" not in vars(ProcurveDriver)
def test_uptime_from_the_switch_mib():
assert PROFILE["uptime"] == {"oids": ["1.3.6.1.4.1.11.2.14.11.1.2.4.1.5.1"]}
def test_cpu_from_the_current_oid_then_the_older_firmware_s():
assert PROFILE["cpu"] == {
"oids": ["1.3.6.1.4.1.11.2.14.11.5.1.9.6.1.0", "1.3.6.1.4.1.11.2.3.7.8.6.1.0"]
}
def test_memory_column_6_is_free_not_used():
# On swt-l0-3-40 (2026-10-16): total (.5) 58720256 = free (.6) 39105640
# + allocated (.7) 19614616. Read as "used", .6 showed 66.6 % instead of 33.4 % (#9).
assert PROFILE["memory"] == {
"total": {"oids": [f"{MEM}.5.1"]},
"free": {"oids": [f"{MEM}.6.1"]},
"unit": "bytes",
}