Files
FabledSteward/plugins/snmp/models.py
T
bvandeusenandClaude Opus 5.5 fcd58224de
CI / lint (push) Successful in 2s
CI / unit (push) Successful in 1m32s
CI / integration (push) Successful in 1m42s
CI / publish (push) Successful in 20s
feat(syslog): a device through Docker's address is placed by its name, or a device address set on it (#6096)
The SNMP poll asks each device's sysName in the same GET and keeps it
(snmp_003_sys_name). A syslog source told apart by name finds its own
address from the SNMP device (reported or given name) or host of that
name, so its lines reach the SNMP device's and host's pages again; the
edit page gains Device address, which always wins (syslog_004).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 12:24:58 -04:00

52 lines
2.9 KiB
Python

# plugins/snmp/models.py
from __future__ import annotations
from datetime import datetime, timezone
from sqlalchemy import JSON, DateTime, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
from steward.core.ids import time_ordered_id
from steward.models.base import Base
class SnmpDevice(Base):
"""A device Steward polls over SNMP, edited on the SNMP page.
Secrets (the community, the v3 keys) are stored encrypted. The last_*
columns are the newest poll's outcome, written by the poller, so a page
can say why a device isn't answering without asking the device itself.
`tables` is the rows the poller found in the presets' vendor tables (a
disk or volume each), as of `tables_at`; `texts` is each state reading's
newest answer in the device's own word.
"""
__tablename__ = "snmp_devices"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=time_ordered_id)
name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True)
address: Mapped[str] = mapped_column(String(255), nullable=False)
port: Mapped[int] = mapped_column(Integer, nullable=False, default=161)
version: Mapped[str] = mapped_column(String(3), nullable=False, default="2c")
community: Mapped[str] = mapped_column(Text, nullable=False, default="")
v3_user: Mapped[str] = mapped_column(String(100), nullable=False, default="")
v3_auth: Mapped[str] = mapped_column(String(16), nullable=False, default="none")
v3_auth_key: Mapped[str] = mapped_column(Text, nullable=False, default="")
v3_priv: Mapped[str] = mapped_column(String(16), nullable=False, default="none")
v3_priv_key: Mapped[str] = mapped_column(Text, nullable=False, default="")
presets: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
interfaces: Mapped[str] = mapped_column(String(255), nullable=False, default="")
custom: Mapped[str] = mapped_column(Text, nullable=False, default="")
host_id: Mapped[str | None] = mapped_column(String(36), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc))
last_polled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
last_ok_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
last_error: Mapped[str | None] = mapped_column(Text, nullable=True)
missing: Mapped[list] = mapped_column(JSON, nullable=False, default=list)
tables: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
tables_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
texts: Mapped[dict] = mapped_column(JSON, nullable=False, default=dict)
# The name the device reports (sysName), asked with every poll: how a
# device whose syslog comes through Docker's address is found (#6096).
sys_name: Mapped[str] = mapped_column(String(255), nullable=False, default="")