# Dashboard API and context contract This document describes the structure of data passed to the index template and returned by the dashboard API endpoints. Cache keys are defined in `dashboard/stats.py`. ## Index page context (server-rendered) When the index is rendered with full data (e.g. `USE_MOCK_DATA=True` or after JS loads from API), the template receives a context with these top-level keys: | Key | Description | |-----|-------------| | `region` | `{ "name": str, "hosts_total": int }` | | `pcpu` | Physical CPU: `total`, `usage`, `free`, `used_percentage` | | `vcpu` | Virtual CPU: `total`, `allocated`, `free`, `allocated_percentage`, `overcommit_ratio`, `overcommit_max` | | `pram` | Physical RAM (bytes): `total`, `usage`, `free`, `used_percentage` | | `vram` | Virtual RAM (bytes): `total`, `allocated`, `free`, `allocated_percentage`, `overcommit_ratio`, `overcommit_max` | | `vm` | VMs: `count`, `active`, `stopped`, `avg_cpu`, `avg_ram`, `density` | | `flavors` | `first_common_flavor`, `second_common_flavor`, `third_common_flavor` — each `{ "name": str, "count": int }` or `None`. The `name` may be a human-readable flavor name or a flavor UUID depending on OpenStack. | | `audits` | List of audit objects (see below). For template, `migrations`, `host_labels`, `cpu_current`, `cpu_projected` are JSON strings. | | `current_cluster` | `{ "host_labels": str (JSON array), "cpu_current": str (JSON array) }` for embedding in the page. | | `skeleton` | Optional boolean; when true, stats placeholders are shown and data is loaded via API. | ## Single audit object (for template / API response) When serialized for the template or for `api/audits`, each audit has: | Field | Type | Description | |-------|------|-------------| | `id` | str | Audit UUID | | `name` | str | Audit name | | `created_at` | str | ISO 8601 datetime | | `strategy` | str | Strategy name | | `goal` | str | Goal name | | `type` | str | e.g. `ONESHOT` | | `scope` | str | e.g. `Full Cluster` | | `cpu_weight` | str | Weight parameter | | `ram_weight` | str | Weight parameter | | `migrations` | str (template) / list (API raw) | JSON string of migration list, or list of `{ instanceName, source, destination, flavor, impact }` | | `host_labels` | str (template) / list (API raw) | JSON string of host names, or list | | `cpu_current` | str (template) / list (API raw) | JSON string of CPU usage per host, or list of numbers | | `cpu_projected` | str (template) / list (API raw) | JSON string of projected CPU per host, or list of numbers | For the **index template**, `migrations`, `host_labels`, `cpu_current`, and `cpu_projected` are always JSON strings so they can be embedded in the page. For **api/audits**, `audits` are returned with these four fields as JSON strings (same as template). The **current_cluster** in the API response uses raw lists (see below). ## GET /api/stats/ Returns a JSON object with the same keys as the index context, **excluding** `audits`, `current_cluster`, and `skeleton`: `region`, `pcpu`, `vcpu`, `pram`, `vram`, `vm`, `flavors`. All numeric values are numbers; sizes are in bytes where applicable. ## GET /api/audits/ Returns: ```json { "audits": [ /* list of audit objects with migrations, host_labels, cpu_current, cpu_projected as JSON strings */ ], "current_cluster": { "host_labels": [ "compute-0", "compute-1", ... ], "cpu_current": [ 30.5, 42.1, ... ] } } ``` Here `audits` use the same serialized form as the template (JSON strings for list fields). The `current_cluster` is with **raw lists** (not JSON strings) so the frontend can use them directly without parsing. ## GET /api/source-status/ Returns: ```json { "prometheus": { "status": "ok" | "error" | "mock", "message"?: "..." }, "openstack": { "status": "ok" | "error" | "mock", "message"?: "..." } } ``` ## Cache keys (dashboard/stats.py) - `CACHE_KEY_STATS` — stats for `/api/stats/` - `CACHE_KEY_AUDITS` — serialized audits list - `CACHE_KEY_CURRENT_CLUSTER` — raw current_cluster (host_labels, cpu_current lists) - `CACHE_KEY_SOURCE_STATUS` — source status result