Files
homelab-infra/apps/dashboard/backend/app/clients/backrest_client.py
T

83 lines
2.8 KiB
Python

from __future__ import annotations
import logging
from datetime import datetime, timezone
from app.clients.base import BaseHTTPClient
from app.config import Settings
from app.models.sources import BackrestSnapshot
logger = logging.getLogger(__name__)
class BackrestClient(BaseHTTPClient):
def __init__(self, settings: Settings) -> None:
super().__init__(settings, "backrest", settings.backrest_base_url)
def _auth(self) -> tuple[str, str] | None:
if self.settings.backrest_username and self.settings.backrest_password:
return (self.settings.backrest_username, self.settings.backrest_password)
return None
async def fetch_status(self) -> BackrestSnapshot:
snapshot = BackrestSnapshot()
if not self.base_url:
logger.info("backrest skipped: base URL missing")
return snapshot
auth = self._auth()
# Get config (repo list) via Connect-RPC
data = await self._request_json(
"POST", "/v1.Backrest/GetConfig",
json={},
auth=auth,
)
if not isinstance(data, dict):
return snapshot
repos = data.get("repos") or []
repo_count = len(repos) if isinstance(repos, list) else 0
# Get recent operations via Connect-RPC
last_backup_age_hours: float | None = None
error_count = 0
last_backup_status = "unknown"
ops_data = await self._request_json(
"POST", "/v1.Backrest/GetOperations",
json={"lastN": 20},
auth=auth,
)
if isinstance(ops_data, dict):
ops = ops_data.get("operations") or []
backup_ops = [
op for op in ops
if isinstance(op, dict) and op.get("backupOp") is not None
]
error_ops = [op for op in backup_ops if op.get("status") == "STATUS_ERROR"]
error_count = len(error_ops)
if backup_ops:
latest = backup_ops[0]
ts = latest.get("unixTimeEndMs")
if ts:
ended = datetime.fromtimestamp(int(ts) / 1000, tz=timezone.utc)
now = datetime.now(timezone.utc)
last_backup_age_hours = round((now - ended).total_seconds() / 3600, 1)
status_str = latest.get("status", "")
if status_str == "STATUS_SUCCESS":
last_backup_status = "ok"
elif status_str == "STATUS_ERROR":
last_backup_status = "error"
else:
last_backup_status = "unknown"
return BackrestSnapshot(
source_status="online",
repo_count=repo_count,
last_backup_age_hours=last_backup_age_hours,
last_backup_status=last_backup_status,
error_count=error_count,
)