from __future__ import annotations from fastapi import APIRouter, Depends from sqlmodel import Session, select from ..connectors.unraid import UnraidConnector from ..core.redaction import redact_message from ..db.models import AuditEvent, Connector from ..db.session import get_session from ..services.incident_service import count_open_incidents from ..services.setup_service import apply_stored_connector_settings, list_connector_settings router = APIRouter(prefix='/api/system') def _gateway_health(unraid_status: str, portainer_status: str, open_incidents: int) -> str: core_statuses = {unraid_status, portainer_status} if core_statuses & {'missing_config', 'error', 'disconnected'}: return 'critical' if open_incidents > 0: return 'warning' return 'healthy' def _latest_action_label(session: Session) -> str | None: event = session.exec(select(AuditEvent).order_by(AuditEvent.timestamp.desc())).first() if event is None: return None action = str(event.action_id or '').strip() target = str(event.target or '').strip() if not action: return None label = f'{action} -> {target}' if target else action return redact_message(label)[:120] @router.get('/summary') def system_summary(session: Session = Depends(get_session)): apply_stored_connector_settings(session) connectors = session.exec(select(Connector)).all() status_map = {connector.id: connector.status for connector in connectors} config_map = {item["connectorId"]: item for item in list_connector_settings(session)} portainer_config = config_map.get('portainer', {}) portainer_status = 'missing_config' if portainer_config.get('missing') else status_map.get('portainer', 'disconnected') if portainer_status not in {'connected', 'missing_config', 'error', 'disconnected'}: portainer_status = 'disconnected' unraid_config = config_map.get('unraid', {}) unraid_status = 'missing_config' if unraid_config.get('missing') else status_map.get('unraid', 'disconnected') if unraid_status not in {'connected', 'missing_config', 'error', 'disconnected'}: unraid_status = 'disconnected' unraid = UnraidConnector() server_info = unraid.get_server_info() if unraid.is_configured() else {'status': 'missing_config'} metrics = unraid.get_system_metrics() if unraid.is_configured() else {'status': 'missing_config'} cache = unraid.get_cache_status() if unraid.is_configured() else {'status': 'missing_config'} server = server_info.get('info', {}) if server_info.get('status') == 'ok' else {} cpu_usage = metrics.get('cpuUsage') if isinstance(metrics.get('cpuUsage'), int | float) else 0 ram_usage = metrics.get('ramUsage') if isinstance(metrics.get('ramUsage'), int | float) else 0 cache_usage = cache.get('cacheUsage') if cache.get('status') == 'ok' and isinstance(cache.get('cacheUsage'), int | float) else 0 open_incidents = count_open_incidents(session) last_action = _latest_action_label(session) return { 'gatewayHealth': _gateway_health(unraid_status, portainer_status, open_incidents), 'unraidStatus': unraid_status, 'portainerStatus': portainer_status, 'maintenanceMode': False, 'openIncidents': open_incidents, 'lastAction': last_action, 'uptime': str(server.get('uptime') or 'unknown'), 'cpuUsage': int(cpu_usage), 'ramUsage': int(ram_usage), 'cacheUsage': int(cache_usage), }