feat: add BackrestClient
This commit is contained in:
@@ -0,0 +1,73 @@
|
|||||||
|
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)
|
||||||
|
|
||||||
|
async def fetch_status(self) -> BackrestSnapshot:
|
||||||
|
snapshot = BackrestSnapshot()
|
||||||
|
if not self.base_url:
|
||||||
|
logger.info("backrest skipped: base URL missing")
|
||||||
|
return snapshot
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = await self._request_json("GET", "/v1/config")
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("backrest fetch_status /v1/config failed: %s", exc)
|
||||||
|
return snapshot
|
||||||
|
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
return snapshot
|
||||||
|
|
||||||
|
repos = data.get("repos") or []
|
||||||
|
repo_count = len(repos) if isinstance(repos, list) else 0
|
||||||
|
|
||||||
|
# Fetch operation log for recent backup status
|
||||||
|
last_backup_age_hours: float | None = None
|
||||||
|
error_count = 0
|
||||||
|
last_backup_status = "unknown"
|
||||||
|
|
||||||
|
try:
|
||||||
|
ops_data = await self._request_json(
|
||||||
|
"POST", "/v1/operations",
|
||||||
|
json={"last_n": 20},
|
||||||
|
)
|
||||||
|
ops = ops_data.get("operations") or [] if isinstance(ops_data, dict) else []
|
||||||
|
backup_ops = [
|
||||||
|
op for op in ops
|
||||||
|
if isinstance(op, dict) and op.get("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", "")
|
||||||
|
last_backup_status = "ok" if status_str == "STATUS_SUCCESS" else "error" if status_str == "STATUS_ERROR" else "unknown"
|
||||||
|
|
||||||
|
except Exception as exc:
|
||||||
|
logger.warning("backrest fetch_status /v1/operations failed: %s", exc)
|
||||||
|
|
||||||
|
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,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user