- enclosure: fetch SES element descriptor page (0x07) and label temp/fan/ psu/voltage elements with human-readable names - temps service + /api/temps: per-enclosure hotspot (max across SES sensors and housed drive temps) plus named SES sensor list - mqtt_publisher: paho-mqtt with HA discovery (device per enclosure, hotspot + per-sensor entities), LWT availability, opt-in via MQTT_HOST - secrets: OpenBao KV v2 reader; MQTT creds sourced from secret/home_assistant with env fallback - compose/requirements/README updated
176 lines
4.1 KiB
Python
176 lines
4.1 KiB
Python
from pydantic import BaseModel
|
|
|
|
|
|
class Enclosure(BaseModel):
|
|
id: str
|
|
sg_device: str | None = None
|
|
vendor: str
|
|
model: str
|
|
revision: str
|
|
total_slots: int
|
|
populated_slots: int
|
|
|
|
|
|
class SlotInfo(BaseModel):
|
|
slot: int
|
|
populated: bool
|
|
device: str | None = None
|
|
|
|
|
|
class DriveDetail(BaseModel):
|
|
device: str
|
|
model: str | None = None
|
|
serial: str | None = None
|
|
wwn: str | None = None
|
|
firmware: str | None = None
|
|
capacity_bytes: int | None = None
|
|
smart_healthy: bool | None = None
|
|
smart_supported: bool = True
|
|
temperature_c: int | None = None
|
|
power_on_hours: int | None = None
|
|
reallocated_sectors: int | None = None
|
|
pending_sectors: int | None = None
|
|
uncorrectable_errors: int | None = None
|
|
wear_leveling_percent: int | None = None
|
|
zfs_pool: str | None = None
|
|
zfs_vdev: str | None = None
|
|
zfs_state: str | None = None
|
|
smart_attributes: list[dict] = []
|
|
|
|
|
|
class DriveHealthSummary(BaseModel):
|
|
device: str
|
|
model: str | None = None
|
|
serial: str | None = None
|
|
wwn: str | None = None
|
|
firmware: str | None = None
|
|
capacity_bytes: int | None = None
|
|
smart_healthy: bool | None = None
|
|
smart_supported: bool = True
|
|
temperature_c: int | None = None
|
|
power_on_hours: int | None = None
|
|
reallocated_sectors: int | None = None
|
|
pending_sectors: int | None = None
|
|
uncorrectable_errors: int | None = None
|
|
zfs_pool: str | None = None
|
|
zfs_vdev: str | None = None
|
|
zfs_state: str | None = None
|
|
health_status: str = "healthy"
|
|
|
|
|
|
class SlotWithDrive(BaseModel):
|
|
slot: int
|
|
populated: bool
|
|
device: str | None = None
|
|
drive: DriveHealthSummary | None = None
|
|
|
|
|
|
class PsuStatus(BaseModel):
|
|
index: int
|
|
name: str | None = None
|
|
status: str
|
|
fail: bool = False
|
|
ac_fail: bool = False
|
|
dc_fail: bool = False
|
|
|
|
|
|
class FanStatus(BaseModel):
|
|
index: int
|
|
name: str | None = None
|
|
status: str
|
|
rpm: int | None = None
|
|
fail: bool = False
|
|
|
|
|
|
class TempSensor(BaseModel):
|
|
index: int
|
|
name: str | None = None
|
|
status: str
|
|
temperature_c: float | None = None
|
|
|
|
|
|
class VoltageSensor(BaseModel):
|
|
index: int
|
|
name: str | None = None
|
|
status: str
|
|
voltage: float | None = None
|
|
|
|
|
|
class EnclosureHealth(BaseModel):
|
|
overall_status: str = "OK"
|
|
psus: list[PsuStatus] = []
|
|
fans: list[FanStatus] = []
|
|
temps: list[TempSensor] = []
|
|
voltages: list[VoltageSensor] = []
|
|
|
|
|
|
class EnclosureWithDrives(BaseModel):
|
|
id: str
|
|
sg_device: str | None = None
|
|
vendor: str
|
|
model: str
|
|
revision: str
|
|
total_slots: int
|
|
populated_slots: int
|
|
slots: list[SlotWithDrive]
|
|
health: EnclosureHealth | None = None
|
|
|
|
|
|
class HostDrive(BaseModel):
|
|
device: str
|
|
drive_type: str = "disk"
|
|
model: str | None = None
|
|
serial: str | None = None
|
|
wwn: str | None = None
|
|
firmware: str | None = None
|
|
capacity_bytes: int | None = None
|
|
smart_healthy: bool | None = None
|
|
smart_supported: bool = True
|
|
temperature_c: int | None = None
|
|
power_on_hours: int | None = None
|
|
reallocated_sectors: int | None = None
|
|
pending_sectors: int | None = None
|
|
uncorrectable_errors: int | None = None
|
|
zfs_pool: str | None = None
|
|
zfs_vdev: str | None = None
|
|
zfs_state: str | None = None
|
|
health_status: str = "healthy"
|
|
megaraid_id: str | None = None
|
|
physical_drives: list["HostDrive"] = []
|
|
|
|
|
|
class Overview(BaseModel):
|
|
healthy: bool
|
|
drive_count: int
|
|
warning_count: int
|
|
error_count: int
|
|
enclosures: list[EnclosureWithDrives]
|
|
host_drives: list[HostDrive] = []
|
|
|
|
|
|
class HealthCheck(BaseModel):
|
|
status: str
|
|
tools: dict[str, bool]
|
|
|
|
|
|
class EnclosureTempSensor(BaseModel):
|
|
index: int
|
|
name: str | None = None
|
|
status: str
|
|
temperature_c: float | None = None
|
|
|
|
|
|
class EnclosureTemps(BaseModel):
|
|
id: str
|
|
vendor: str
|
|
model: str
|
|
hotspot_c: float | None = None
|
|
drive_max_c: float | None = None
|
|
drive_temp_count: int = 0
|
|
sensors: list[EnclosureTempSensor] = []
|
|
|
|
|
|
class TempSnapshot(BaseModel):
|
|
node: str
|
|
enclosures: list[EnclosureTemps] = []
|