a64749ccc8
Replace the single fixed /records path with a list of storages and an
active selection (where new recordings go). Quota is now per-storage.
- config: StorageItem(id,name,type,path,quota_gb,nas-meta) + Storage keeps
global retention_days/segment_seconds; active + items. Migration from the
old single {path,quota_gb} schema → one local item.
- recorder: write to the active storage; restart_all() repoints on switch;
NAS-not-mounted guard (never write into the container overlay).
- indexer: scan ALL storage roots so recordings survive an active switch.
- retention: enforce quota PER storage via db.total_size_under /
oldest_recordings_under (path-prefix LIKE).
- api/storages: GET/POST/PUT/DELETE + activate + policy. NAS uses host-mount
(backend stores SMB params, generates the mount/fstab command, reports
ismount status). Retire old POST /api/storage.
- frontend: new "Хранилища" settings tab — table with inline per-row quota,
add form (local folder / NAS SMB), global policy (segment + retention).
- compose: add shared ./storages:/storages root for extra local folders and
host-mounted NAS shares.
VERSION 0.0.127.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
36 lines
906 B
Python
36 lines
906 B
Python
"""REST: системная статистика и сводный статус."""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
|
|
from fastapi import APIRouter
|
|
|
|
from ..runtime import runtime
|
|
from ..services.system import system_stats
|
|
|
|
router = APIRouter(prefix="/api", tags=["system"])
|
|
|
|
VERSION_FILE = os.environ.get("NVR_VERSION_FILE", "/app/VERSION")
|
|
|
|
|
|
def app_version() -> str:
|
|
try:
|
|
with open(VERSION_FILE, "r", encoding="utf-8") as fh:
|
|
return fh.read().strip()
|
|
except OSError:
|
|
return "0.0.0"
|
|
|
|
|
|
@router.get("/system")
|
|
async def get_system() -> dict:
|
|
stats = system_stats(runtime.config)
|
|
stats["cameras"] = [s.to_dict() for s in runtime.supervisor.statuses()]
|
|
stats["archive_size_bytes"] = await runtime.db.total_size()
|
|
stats["version"] = app_version()
|
|
return stats
|
|
|
|
|
|
@router.get("/health")
|
|
async def health() -> dict:
|
|
return {"status": "ok"}
|