🚧 WIP
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
"""System administration (spec sections 29, 41, 46).
|
||||
|
||||
Broker status and restart through the control sidecar. The restart
|
||||
primitive is SIGTERM to PID 1 in the broker's (shared) PID namespace —
|
||||
the broker shuts down gracefully (persistence saved) and Docker's
|
||||
`restart: unless-stopped` policy brings the container back. No Docker
|
||||
socket is involved (spec section 29).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app import audit
|
||||
from app.db import get_db
|
||||
from app.deps import CurrentUser, require_roles
|
||||
from app.models import ManagementRole
|
||||
from app.routers.broker import _call_control, restart_required
|
||||
|
||||
router = APIRouter(prefix="/api/v1/system", tags=["system"])
|
||||
|
||||
BrokerAdmin = Annotated[CurrentUser, Depends(require_roles(ManagementRole.BROKER_ADMIN))]
|
||||
AnyReader = Annotated[
|
||||
CurrentUser,
|
||||
Depends(
|
||||
require_roles(
|
||||
ManagementRole.BROKER_ADMIN,
|
||||
ManagementRole.OPERATOR,
|
||||
ManagementRole.AUDITOR,
|
||||
)
|
||||
),
|
||||
]
|
||||
DbDep = Annotated[Session, Depends(get_db)]
|
||||
|
||||
|
||||
@router.get("/status")
|
||||
def system_status(db: DbDep, _user: AnyReader):
|
||||
"""Broker process state + pending-restart flag (spec section 46).
|
||||
|
||||
Used by the sidebar indicator (polls lightly) and the System page.
|
||||
The control call is allowed to fail — an unreachable sidecar is a
|
||||
status, not an error.
|
||||
"""
|
||||
try:
|
||||
control = _call_control("/status", method="GET")
|
||||
broker_alive = bool(control.get("broker_pid_alive"))
|
||||
except Exception: # noqa: BLE001 - status endpoint must not 500
|
||||
broker_alive = False
|
||||
return {
|
||||
"broker_alive": broker_alive,
|
||||
"restart_required": restart_required(db),
|
||||
}
|
||||
|
||||
|
||||
@router.post("/broker/restart")
|
||||
def restart_broker(request: Request, db: DbDep, user: BrokerAdmin):
|
||||
"""Restart the broker via the control sidecar (spec section 29).
|
||||
|
||||
The sidecar acknowledges and then SIGTERMs PID 1; Docker restarts
|
||||
the container. The pending-restart flag is cleared here — the config
|
||||
on disk is what the broker will boot with, so listener changes take
|
||||
effect by definition once the restart completes.
|
||||
"""
|
||||
from app.routers.broker import _set_restart_required
|
||||
|
||||
response = _call_control("/restart")
|
||||
_set_restart_required(db, False)
|
||||
audit.record(
|
||||
db,
|
||||
"BROKER_RESTARTED",
|
||||
request=request,
|
||||
user=user.username,
|
||||
object_type="broker",
|
||||
object_id="mosquitto",
|
||||
result="initiated",
|
||||
)
|
||||
return {"status": "restarting", "broker_alive": False}
|
||||
Reference in New Issue
Block a user