c2bb0465d0
Adds diagrams and expands the ATC demo path so the cockpit is fully described in-repo.
6.6 KiB
6.6 KiB
Architecture
1. System context
OME Cockpit is a BFF + SPA running on atc-portal01 (Docker). It does not embed OME; it continuously aggregates OME REST data, enriches with GPU telemetry and LLM chat, and pushes live snapshots to browsers over WebSocket.
Actors
| Actor | Role |
|---|---|
| ATC admin (browser) | Operates fleet via UI |
| OpenManage Enterprise | Source of truth for devices/alerts/inventory |
vLLM (atc-gpu-prod:8000) |
LLM inference for Cockpit chat |
Open WebUI (:3080) |
Model catalog + virtual models (ome-copilot, arena-model) |
GPU metrics sidecar (:9110) |
NVIDIA V100 utilization/power |
| Target servers / iDRACs | SSH endpoints opened from the browser via cockpit bridge |
2. Runtime components
┌─────────────────────────────────────────────────────────────┐
│ Docker: ome-cockpit │
│ uvicorn → FastAPI (main.py) :8090 → host :3090 │
│ │
│ Background tasks: │
│ • poll_loop() ~POLL_INTERVAL (default 12–15s) │
│ • gpu_loop() ~2s │
│ │
│ In-memory STATE + WebSocket fan-out │
│ SQLite tickets → /data/ops.db │
│ Static UI → /ui (bind-mount) │
└─────────────────────────────────────────────────────────────┘
Process model
- Single uvicorn worker (important): fleet
STATE, WebSocket client sets, and SSH session registry are in-process memory. Do not scale to multiple workers without an external shared store. - UI assets and
main.pyare bind-mounted for lab hot-reload; image rebuild needed when Python dependencies change (asyncssh, etc.).
3. Data flows
3.1 Fleet snapshot (OME → UI)
poll_loopauthenticates to OMESessionService/Sessions- Fetches devices, groups, alerts (paged
$top) - For a capped set of connected servers, fetches
/Power - Normalizes into cockpit device nodes (
is_server,is_idrac, subnet, watts, …) - Diffs against
PREV_DEVICES→EVENT_FEED(connection/power/status + device_new / device_removed) - Writes
STATE, broadcasts{type:"snapshot", data: STATE}to all/ws/fleetclients
Browser app.js applies snapshot → layout → canvas draw loop; ops.js updates GPU, tickets, notifications.
3.2 Device inventory (on demand)
GET /api/devices/{id}:
- Resolves node from current
STATE - Opens OME session
- Reads
InventoryTypesfor that device and pulls eachInventoryDetails('…') - Builds normalized
landscape(OS, firmware, drivers, applications, management, licenses) - Caches in
DETAIL_CACHE(~300s)
3.3 Chat
POST /api/chat:
- Builds compact fleet system prompt (
build_fleet_context, char-budgeted for 4096-token models) - Routes:
llama3-70b-gptq(and similar) → direct vLLM/v1/chat/completionsome-copilot/arena-model→ Open WebUI/api/chat/completions(service login)
- Retries with tighter context on vLLM context-length 400 errors
3.4 SSH bridge
Browser ssh.js (xterm) → WS /ws/ssh:
- First message: JSON
{type:"auth", host, port, username, password, cols, rows} - Server allowlists
hostagainst current fleet IPs only asyncssh.connect+ interactive shell process- Bidirectional pump; resize via JSON control messages
- Concurrency: global semaphore (25) + max 3 sessions per client IP; idle timeout 30 min
3.5 GPU telemetry
gpu_loop polls GPU_METRICS_URL/api/gpu every ~2s and broadcasts {type:"gpu"} (and embeds GPU in fleet snapshots).
4. Frontend architecture
| File | Responsibility |
|---|---|
index.html |
App chrome, rails, stage, drawers, modals (KPI, triage, connect, SSH, tickets) |
app.js |
Canvas topology, camera, filters, KPIs, inspector, inventory render, KPI popup |
ops.js |
Ops desk CRUD, chat drawer, triage modal, live-feed collapse/drag, GPU matrix |
ssh.js |
SSH modal + xterm session lifecycle |
styles.css |
Design tokens + component styles |
vendor/xterm/* |
Local terminal assets (CDN-independent) |
State
- Primary client state lives in
app.jsstate(data, filters, camera, layoutMode, inventoryCache, …) - Shared bridge:
window.cockpitandwindow.cockpitSsh
Rendering
- Topology is an immediate-mode canvas (
requestAnimationFrame), not DOM nodes for devices - Camera = translate + scale; layouts write target coordinates (
tx/ty) with lerp for motion - Pulse packets on links are decorative; toggle via Animate link pulse
5. Persistence
| Store | Path | Contents |
|---|---|---|
| SQLite | /data/ops.db (COCKPIT_DATA) |
Tickets + ticket_messages |
| Browser localStorage | client | feed_collapsed, feed_bottom, cockpit_ssh_user, cockpit_chat_model, actor |
| In-memory | process | Fleet STATE, DETAIL_CACHE, SSH_SESSIONS, EVENT_FEED |
6. External contracts
OME (OpenManage Enterprise 4.7)
- Session auth header
X-Auth-Token - Device types: server
Type == 1000; iDRAC viaSubDeviceType == "iDRAC" - Inventory via per-device
InventoryTypes+InventoryDetails
vLLM OpenAI-compatible API
GET /v1/models,POST /v1/chat/completions- Lab model
llama3-70b-gptqwith max context 4096 → prompt budgeting is mandatory
Open WebUI
- Sign-in → Bearer token (cached ~1h)
GET /api/models,POST /api/chat/completions
7. Failure domains
| Failure | UX impact | Mitigation |
|---|---|---|
| OME down | Stale/empty fleet | Health + last updated_at; poll retries |
| vLLM 400 context | Chat errors | Slim context + retry |
| Open WebUI auth missing | Virtual models unavailable | Falls back to vLLM list / error message |
| SSH to non-fleet IP | Rejected | Allowlist |
| Multi-user SSH overload | Queue/reject | Semaphore + per-IP cap |
| Soft inspector refresh | Inventory preserved | softRefreshInspector + inventory cache |
8. Related systems (out of repo)
- OpenManage AI (
mo/openmanage-ai): Open WebUI branding + OME REST tool for demos - Native OME MCP at
https://ome/mcpexists but session stickiness is unreliable in this lab — Cockpit does not depend on it