feat: add /host-sys volume mount and HOST_SYS_PATH environment variable for sysfs serial fallback and SMART health detection
Add HOST_SYS_PATH=/host-sys to .env.example and app.py config with /host-sys default. Update _device_serial() to check HOST_SYS_PATH/class/block and HOST_SYS_PATH/block before fallback /sys paths for serial reads. Update raid_status() SMART regex to match both "SMART overall-health self-assessment test result" and "SMART Health Status" with case-insensitive flag for NVMe/SSD compatibility. Add /
This commit is contained in:
@@ -37,4 +37,5 @@ RAID_DEVICE=/dev/md127
|
|||||||
STORAGE_CACHE_SECONDS=900
|
STORAGE_CACHE_SECONDS=900
|
||||||
# Optional: SMART-Abfragen aktivieren (benötigt Zugriff auf Host-Devices)
|
# Optional: SMART-Abfragen aktivieren (benötigt Zugriff auf Host-Devices)
|
||||||
SMART_ENABLED=false
|
SMART_ENABLED=false
|
||||||
|
HOST_SYS_PATH=/host-sys
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ REQUEST_TIMEOUT = int(os.environ.get("REQUEST_TIMEOUT", "20"))
|
|||||||
DATASTORE_PATH = os.environ.get("DATASTORE_PATH", "/nesflix").rstrip("/") or "/"
|
DATASTORE_PATH = os.environ.get("DATASTORE_PATH", "/nesflix").rstrip("/") or "/"
|
||||||
RAID_DEVICE = os.environ.get("RAID_DEVICE", "/dev/md127")
|
RAID_DEVICE = os.environ.get("RAID_DEVICE", "/dev/md127")
|
||||||
HOST_DEVICE_PATH = os.environ.get("HOST_DEVICE_PATH", "/host-dev")
|
HOST_DEVICE_PATH = os.environ.get("HOST_DEVICE_PATH", "/host-dev")
|
||||||
|
HOST_SYS_PATH = os.environ.get("HOST_SYS_PATH", "/host-sys")
|
||||||
STORAGE_CACHE_SECONDS = int(os.environ.get("STORAGE_CACHE_SECONDS", "900"))
|
STORAGE_CACHE_SECONDS = int(os.environ.get("STORAGE_CACHE_SECONDS", "900"))
|
||||||
SMART_ENABLED = os.environ.get("SMART_ENABLED", "false").lower() in {"1", "true", "yes", "on"}
|
SMART_ENABLED = os.environ.get("SMART_ENABLED", "false").lower() in {"1", "true", "yes", "on"}
|
||||||
|
|
||||||
@@ -243,7 +244,7 @@ def _flatten_lsblk(nodes):
|
|||||||
def _device_serial(device):
|
def _device_serial(device):
|
||||||
"""Read a disk serial from sysfs when lsblk cannot expose it in Docker."""
|
"""Read a disk serial from sysfs when lsblk cannot expose it in Docker."""
|
||||||
name = Path(device).name
|
name = Path(device).name
|
||||||
for path in (Path("/sys/class/block") / name / "device/serial", Path("/sys/block") / name / "device/serial"):
|
for path in (Path(HOST_SYS_PATH) / "class/block" / name / "device/serial", Path(HOST_SYS_PATH) / "block" / name / "device/serial", Path("/sys/class/block") / name / "device/serial", Path("/sys/block") / name / "device/serial"):
|
||||||
try:
|
try:
|
||||||
value = path.read_text().strip()
|
value = path.read_text().strip()
|
||||||
if value:
|
if value:
|
||||||
@@ -357,7 +358,7 @@ def raid_status():
|
|||||||
if SMART_ENABLED and shutil.which("smartctl"):
|
if SMART_ENABLED and shutil.which("smartctl"):
|
||||||
smart_device = disk["device"].replace("/dev/", f"{HOST_DEVICE_PATH.rstrip('/')}/", 1)
|
smart_device = disk["device"].replace("/dev/", f"{HOST_DEVICE_PATH.rstrip('/')}/", 1)
|
||||||
smart_output, _ = _read_command(["smartctl", "-H", smart_device], timeout=6)
|
smart_output, _ = _read_command(["smartctl", "-H", smart_device], timeout=6)
|
||||||
health = re.search(r"SMART overall-health self-assessment test result:\s*(.+)", smart_output)
|
health = re.search(r"(?:SMART overall-health self-assessment test result|SMART Health Status):\s*(.+)", smart_output, re.IGNORECASE)
|
||||||
disk["smart"] = health.group(1).strip() if health else "Nicht verfügbar"
|
disk["smart"] = health.group(1).strip() if health else "Nicht verfügbar"
|
||||||
missing = members_match and members_match.group(1) != members_match.group(2)
|
missing = members_match and members_match.group(1) != members_match.group(2)
|
||||||
failed = detail.get("failed_devices", 0) > 0 or any(disk["status"] == "failed" for disk in devices)
|
failed = detail.get("failed_devices", 0) > 0 or any(disk["status"] == "failed" for disk in devices)
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ services:
|
|||||||
- "8099:8099"
|
- "8099:8099"
|
||||||
devices:
|
devices:
|
||||||
- "${RAID_DEVICE:-/dev/md127}:${RAID_DEVICE:-/dev/md127}"
|
- "${RAID_DEVICE:-/dev/md127}:${RAID_DEVICE:-/dev/md127}"
|
||||||
|
cap_add:
|
||||||
|
- SYS_RAWIO
|
||||||
|
device_cgroup_rules:
|
||||||
|
- "b 8:* rwm"
|
||||||
|
- "b 9:* rwm"
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- "host.docker.internal:host-gateway"
|
- "host.docker.internal:host-gateway"
|
||||||
env_file:
|
env_file:
|
||||||
@@ -20,6 +25,8 @@ services:
|
|||||||
- ${DATASTORE_HOST_PATH:-/nesflix}:/nesflix:ro
|
- ${DATASTORE_HOST_PATH:-/nesflix}:/nesflix:ro
|
||||||
# Read-only Host-Devices für lsblk/smartctl; Media Max führt keine RAID-Schreiboperationen aus.
|
# Read-only Host-Devices für lsblk/smartctl; Media Max führt keine RAID-Schreiboperationen aus.
|
||||||
- /dev:/host-dev:ro
|
- /dev:/host-dev:ro
|
||||||
|
# Read-only Hardware-Metadaten für Seriennummern und SMART-Zuordnung.
|
||||||
|
- /sys:/host-sys:ro
|
||||||
- ./data:/data
|
- ./data:/data
|
||||||
networks:
|
networks:
|
||||||
- media
|
- media
|
||||||
|
|||||||
Reference in New Issue
Block a user