CreaRack-SL

Modelo AgentRoleEvent — historial de cambios de rol de la flota

Propósito

AgentRoleEvent (terminal/models.py) es el rastro persistente de cada cambio de rol Primary/Secondary en la flota de Agentes de una organización. Antes de este modelo (task #234, v1.88.0) un cambio de Primary solo dejaba un logger.info que nadie consultaba; ahora cada transición real de rol (from_role != to_role) queda como una fila consultable desde el Fleet Manager.

Contrato

Campos principales (migración terminal/0007_agentroleevent.py + RLS gemela 0008_agentroleevent_rls.py, mismo patrón que network/0063):

CampoTipoNotas
organizationFK → Organization, on_delete=CASCADEancla RLS multi-tenant, related_name="agent_role_events"
agent_idCharField(64), db_index=Trueplano, no FK — sobrevive a la purga del AgentInstance (fantasmas offline >24h)
hostnameCharField(255), opcionalidem, plano
from_role / to_roleCharField(16)from_role vacío = asignación inicial de un Agente recién instalado
causeCharField, choices manual / failover / auto_assign
actorFK → User, SET_NULL, null=TrueNone = lo hizo el sistema (failover o asignación automática)
from_agent_id / from_hostnameCharField, opcionalel Primary relevado, cuando la transición releva a otro
created_atDateTimeField(auto_now_add=True)

Meta.ordering = ["-created_at"]; índice compuesto (organization, -created_at).

Dependencias

  • Lo escribe terminal.fleet_events.record_role_change() — única puerta de entrada, llamada desde cuatro sitios: terminal/api/fleet.py::promote_agent/demote_agent (causa manual), terminal/fleet_lifecycle.py::_handle_disconnect_failover (causa failover) y _register_and_assign_role (causa failover para el barrido de Primaries caducados, auto_assign para el registro de un Agente nuevo).
  • record_role_change es best-effort: un fallo al guardar se captura con logger.exception y devuelve None, sin romper la promoción o el failover que lo llamó. Si from_role == to_role (no hubo transición real) tampoco escribe nada.
  • Cuando la transición deja to_role="primary" y había un from_role previo, dispara además notify_primary_change() (mismo módulo) — correo best-effort a los admins de la organización.
  • Lo lee el endpoint GET /api/agent/fleet/history (terminal/api/fleet.py::fleet_role_history, permiso fleet:view, máx 200 filas) y la sección Role changes del Fleet Manager en el frontend.

Ejemplo de uso

from terminal.fleet_events import record_role_change

record_role_change(
    organization_id=org.id,
    agent_id=agent.agent_id,
    hostname=agent.hostname,
    from_role="secondary",
    to_role="primary",
    cause="manual",
    actor=request.user,
    from_agent_id=previous_primary.agent_id,
    from_hostname=previous_primary.hostname,
)

Véase también

  • [[entity—terminal—model—agentinstance]]
  • [[entity—terminal—endpoint—fleet]]
  • [[feature—terminal—fleet-role-history]]
  • [[concept—saas—multi-tenancy]]
  • [[entity—core—model—systemlog]]
  • [[crearack—monitoring—fleet-manager]]