update 1.2.4.1 beta - apis

This commit is contained in:
MacRimi
2026-08-01 11:29:32 +02:00
parent f2d9c9fb8e
commit 7fcbc467df
4 changed files with 559 additions and 1 deletions
@@ -63,6 +63,7 @@ export default async function MonitorApiPage({
auth: { rows: EndpointRow[]; items: string[] }
conventions: { items: string[] }
system: { rows: EndpointRow[] }
actions: { rows: EndpointRow[] }
health: { rows: EndpointRow[] }
storage: { rows: EndpointRow[] }
network: { rows: EndpointRow[] }
@@ -81,6 +82,7 @@ export default async function MonitorApiPage({
const authItems = api.auth.items
const conventionsItems = api.conventions.items
const systemRows = api.system.rows
const actionsRows = api.actions.rows
const healthRows = api.health.rows
const storageRows = api.storage.rows
const networkRows = api.network.rows
@@ -181,6 +183,29 @@ export default async function MonitorApiPage({
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("system.heading")}</h2>
{endpointTable(systemRows, "system.rows")}
<h2 id="actions" className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("actions.heading")}</h2>
<p className="mb-4 text-gray-800 leading-relaxed">{t.rich("actions.intro", { code })}</p>
<h3 className="text-lg font-semibold mt-6 mb-2 text-gray-900">{t("actions.shapeTitle")}</h3>
<p className="mb-2 text-gray-800 leading-relaxed">{t("actions.shapeIntro")}</p>
<CopyableCode code={t("actions.shapeCode")} className="my-4" />
<h3 className="text-lg font-semibold mt-6 mb-2 text-gray-900">{t("actions.concurrencyTitle")}</h3>
<p className="mb-4 text-gray-800 leading-relaxed">{t.rich("actions.concurrencyBody", { code })}</p>
{endpointTable(actionsRows, "actions.rows")}
<h3 className="text-lg font-semibold mt-6 mb-2 text-gray-900">{t("actions.syncVsAsyncTitle")}</h3>
<p className="mb-4 text-gray-800 leading-relaxed">{t.rich("actions.syncVsAsyncBody", { code })}</p>
<h3 className="text-lg font-semibold mt-6 mb-2 text-gray-900">{t("actions.curlTitle")}</h3>
<p className="mb-2 text-gray-800 leading-relaxed">{t("actions.curlBody")}</p>
<CopyableCode code={t("actions.curlCode")} className="my-4" />
<h3 className="text-lg font-semibold mt-6 mb-2 text-gray-900">{t("actions.haTitle")}</h3>
<p className="mb-2 text-gray-800 leading-relaxed">{t.rich("actions.haBody", { code })}</p>
<CopyableCode code={t("actions.haCode")} className="my-4" />
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("health.heading")}</h2>
{endpointTable(healthRows, "health.rows")}
<p className="mb-4 text-gray-800 leading-relaxed">
@@ -100,6 +100,85 @@
}
]
},
"actions": {
"heading": "System actions",
"intro": "Fire-and-forget endpoints that trigger the same operations the operator would run from the Monitor UI or the shell menu — designed for Home Assistant, Homepage, Ansible, custom dashboards and any other automation that needs to reach into the host over HTTP. Every mutating route requires a token with <code>full_admin</code> scope; read-only <code>read_only</code> tokens can still poll the <code>.../status</code> endpoints without triggering anything. Each action returns 202 with a state snapshot; poll the matching <code>.../status</code> to observe progress.",
"shapeTitle": "Common response shape",
"shapeIntro": "All action endpoints return the same JSON object — one shape to parse from any client:",
"shapeCode": "{\n \"unit\": \"proxmenux-action-pve-update.service\",\n \"state\": \"idle | running | success | failed | cancelled\",\n \"started_at\": \"Sat 2026-08-01 11:01:32 CEST\",\n \"finished_at\": null,\n \"exit_code\": null,\n \"result\": null\n}",
"concurrencyTitle": "Concurrency and cancellation",
"concurrencyBody": "A second POST while a run is in flight returns 409 with the current running state. Cancel an in-flight run with a DELETE to the action's base URL; the state moves to <code>cancelled</code> and timestamps are preserved so the caller can still see when it was triggered and stopped. The last terminal state (success / failed / cancelled) is remembered until the next run replaces it.",
"rows": [
{
"endpoint": "/api/system/power/reboot",
"method": "POST",
"use": "Reboot the Proxmox host. Fire-and-forget — the HTTP connection drops when systemd starts the shutdown sequence."
},
{
"endpoint": "/api/system/power/reboot/status",
"method": "GET",
"use": "State of the last / current reboot action."
},
{
"endpoint": "/api/system/power/shutdown",
"method": "POST",
"use": "Power off the Proxmox host. Useful as an effect wired to a UPS shutdown signal."
},
{
"endpoint": "/api/system/power/shutdown/status",
"method": "GET",
"use": "State of the last / current shutdown action."
},
{
"endpoint": "/api/system/pve-update/run",
"method": "POST",
"use": "Trigger the safe PVE update flow (the same one the Health Monitor's Update Now button and the shell menu run — delegates to update-pve-safe.sh)."
},
{
"endpoint": "/api/system/pve-update/status",
"method": "GET",
"use": "State of the last / current PVE update run."
},
{
"endpoint": "/api/system/pve-update",
"method": "DELETE",
"use": "Cancel a PVE update in progress (SIGTERM to the running script)."
},
{
"endpoint": "/api/proxmenux/self-update/run",
"method": "POST",
"use": "Update ProxMenux itself by piping the canonical stable installer. Runs in its own systemd unit so the update completes across the proxmenux-monitor restart the installer performs."
},
{
"endpoint": "/api/proxmenux/self-update/status",
"method": "GET",
"use": "State of the last / current ProxMenux self-update run."
},
{
"endpoint": "/api/vms/<vmid>/control",
"method": "POST",
"use": "Start / stop / shutdown / reboot a VM or LXC container (the same operations the Monitor's VM & LXC modal exposes). Body: {\"action\": \"start|stop|shutdown|reboot\"}. Synchronous — returns the outcome directly with no polling needed."
},
{
"endpoint": "/api/vms/<vmid>/backup",
"method": "POST",
"use": "Create a vzdump backup of a VM or LXC. Body (all optional except when the defaults don't match your storage layout): {\"storage\": \"<pve-storage>\", \"mode\": \"snapshot|suspend|stop\", \"compress\": \"zstd|lzo|gz|none\", \"protected\": true, \"notes\": \"…\", \"notification\": \"auto|always|failure|never\", \"pbs_change_detection\": \"default|legacy|data\"}. Returns the PVE task UPID."
},
{
"endpoint": "/api/vms/<vmid>/backups",
"method": "GET",
"use": "List previous backups for a VM or LXC across all reachable storages."
}
],
"syncVsAsyncTitle": "Two flavours of action",
"syncVsAsyncBody": "System-level actions (host power, PVE update, ProxMenux self-update) can take minutes — they run in their own transient systemd unit and expose a <code>.../status</code> endpoint plus a <code>DELETE</code> to cancel. VM / LXC actions (start, stop, shutdown, reboot, backup) are fast and use the fire-and-return style the Monitor's UI already exposes: the POST returns the outcome directly. Both flavours share the same authentication model (JWT or long-lived API token).",
"curlTitle": "curl example",
"curlBody": "Fire a PVE update and poll for completion — the exact same sequence a Home Assistant automation or an Ansible playbook would run:",
"curlCode": "TOKEN=<your full_admin token>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"final state: $state\"",
"haTitle": "Home Assistant integration snippet",
"haBody": "A <code>rest</code> sensor polls the state and a <code>rest_command</code> triggers the update. Wire both to a dashboard button and to any automation you like:",
"haCode": "# configuration.yaml\nsensor:\n - platform: rest\n resource: https://pve.local:8008/api/system/pve-update/status\n name: pve_update_state\n value_template: \"{{ value_json.state }}\"\n scan_interval: 60\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\nrest_command:\n pve_update:\n url: https://pve.local:8008/api/system/pve-update/run\n method: POST\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Start VM 100 (works for LXC too — same endpoint)\n vm_100_start:\n url: https://pve.local:8008/api/vms/100/control\n method: POST\n content_type: 'application/json'\n payload: '{\"action\": \"start\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Backup VM 100 to the 'pbs-main' storage\n vm_100_backup:\n url: https://pve.local:8008/api/vms/100/backup\n method: POST\n content_type: 'application/json'\n payload: '{\"storage\": \"pbs-main\", \"mode\": \"snapshot\", \"compress\": \"zstd\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\""
},
"health": {
"heading": "Health Monitor",
"rows": [
@@ -100,6 +100,85 @@
}
]
},
"actions": {
"heading": "Acciones del sistema",
"intro": "Endpoints fire-and-forget que disparan las mismas operaciones que el usuario ejecutaría desde la interfaz del Monitor o desde el menú shell — pensados para Home Assistant, Homepage, Ansible, paneles personalizados y cualquier otra automatización que necesite alcanzar al host por HTTP. Toda ruta que muta el estado requiere un token con scope <code>full_admin</code>; los tokens <code>read_only</code> pueden consultar los endpoints <code>.../status</code> sin disparar nada. Cada acción devuelve 202 con una instantánea del estado; el cliente hace polling al <code>.../status</code> correspondiente para observar el progreso.",
"shapeTitle": "Formato de respuesta común",
"shapeIntro": "Todos los endpoints de acción devuelven el mismo objeto JSON — una sola forma que parsear desde cualquier cliente:",
"shapeCode": "{\n \"unit\": \"proxmenux-action-pve-update.service\",\n \"state\": \"idle | running | success | failed | cancelled\",\n \"started_at\": \"Sat 2026-08-01 11:01:32 CEST\",\n \"finished_at\": null,\n \"exit_code\": null,\n \"result\": null\n}",
"concurrencyTitle": "Concurrencia y cancelación",
"concurrencyBody": "Un segundo POST mientras una ejecución está en curso devuelve 409 con el estado actual. Cancela una ejecución en curso con un DELETE a la URL base de la acción; el estado pasa a <code>cancelled</code> y los timestamps se conservan para que el cliente vea cuándo se disparó y se detuvo. El último estado terminal (success / failed / cancelled) se recuerda hasta que la siguiente ejecución lo reemplace.",
"rows": [
{
"endpoint": "/api/system/power/reboot",
"method": "POST",
"use": "Reiniciar el host Proxmox. Fire-and-forget — la conexión HTTP cae cuando systemd inicia la secuencia de apagado."
},
{
"endpoint": "/api/system/power/reboot/status",
"method": "GET",
"use": "Estado de la última / actual acción de reinicio."
},
{
"endpoint": "/api/system/power/shutdown",
"method": "POST",
"use": "Apagar el host Proxmox. Útil como efecto conectado a una señal de apagado del SAI."
},
{
"endpoint": "/api/system/power/shutdown/status",
"method": "GET",
"use": "Estado de la última / actual acción de apagado."
},
{
"endpoint": "/api/system/pve-update/run",
"method": "POST",
"use": "Disparar el flujo seguro de actualización de PVE (el mismo que ejecuta el botón Update Now del Health Monitor y el menú shell — delega en update-pve-safe.sh)."
},
{
"endpoint": "/api/system/pve-update/status",
"method": "GET",
"use": "Estado de la última / actual ejecución de actualización de PVE."
},
{
"endpoint": "/api/system/pve-update",
"method": "DELETE",
"use": "Cancelar una actualización de PVE en curso (SIGTERM al script en ejecución)."
},
{
"endpoint": "/api/proxmenux/self-update/run",
"method": "POST",
"use": "Actualizar el propio ProxMenux canalizando el instalador estable canónico. Corre en su propia unit systemd para que la actualización complete a pesar del reinicio de proxmenux-monitor que el instalador realiza."
},
{
"endpoint": "/api/proxmenux/self-update/status",
"method": "GET",
"use": "Estado de la última / actual ejecución de self-update de ProxMenux."
},
{
"endpoint": "/api/vms/<vmid>/control",
"method": "POST",
"use": "Encender / apagar / apagar limpio / reiniciar una VM o contenedor LXC (las mismas operaciones que expone la modal VM & LXC del Monitor). Body: {\"action\": \"start|stop|shutdown|reboot\"}. Síncrono — devuelve el resultado directo sin necesidad de polling."
},
{
"endpoint": "/api/vms/<vmid>/backup",
"method": "POST",
"use": "Crear un backup vzdump de una VM o LXC. Body (todo opcional excepto cuando los defaults no encajan con tu layout de storage): {\"storage\": \"<pve-storage>\", \"mode\": \"snapshot|suspend|stop\", \"compress\": \"zstd|lzo|gz|none\", \"protected\": true, \"notes\": \"…\", \"notification\": \"auto|always|failure|never\", \"pbs_change_detection\": \"default|legacy|data\"}. Devuelve el UPID de la tarea PVE."
},
{
"endpoint": "/api/vms/<vmid>/backups",
"method": "GET",
"use": "Listar backups anteriores de una VM o LXC en todos los storages accesibles."
}
],
"syncVsAsyncTitle": "Dos estilos de acción",
"syncVsAsyncBody": "Las acciones a nivel de sistema (power del host, PVE update, self-update de ProxMenux) pueden tardar minutos — corren en su propia unit systemd transitoria y exponen un endpoint <code>.../status</code> más un <code>DELETE</code> para cancelar. Las acciones VM / LXC (start, stop, shutdown, reboot, backup) son rápidas y usan el estilo fire-and-return que la UI del Monitor ya expone: el POST devuelve el resultado directo. Ambos estilos comparten el mismo modelo de autenticación (JWT o token de API de larga duración).",
"curlTitle": "Ejemplo con curl",
"curlBody": "Disparar una actualización de PVE y hacer polling hasta que termine — exactamente la misma secuencia que ejecutaría una automatización de Home Assistant o un playbook de Ansible:",
"curlCode": "TOKEN=<tu token full_admin>\n\ncurl -sSf -X POST \\\n -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/run\n\nwhile true; do\n state=$(curl -sSf -H \"Authorization: Bearer $TOKEN\" \\\n https://<host>:8008/api/system/pve-update/status | jq -r .state)\n [ \"$state\" != \"running\" ] && break\n sleep 30\ndone\necho \"estado final: $state\"",
"haTitle": "Snippet de integración con Home Assistant",
"haBody": "Un sensor <code>rest</code> hace polling del estado y un <code>rest_command</code> dispara la actualización. Conecta ambos a un botón del dashboard y a las automatizaciones que quieras:",
"haCode": "# configuration.yaml\nsensor:\n - platform: rest\n resource: https://pve.local:8008/api/system/pve-update/status\n name: pve_update_state\n value_template: \"{{ value_json.state }}\"\n scan_interval: 60\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\nrest_command:\n pve_update:\n url: https://pve.local:8008/api/system/pve-update/run\n method: POST\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Encender VM 100 (funciona igual para LXC — mismo endpoint)\n vm_100_start:\n url: https://pve.local:8008/api/vms/100/control\n method: POST\n content_type: 'application/json'\n payload: '{\"action\": \"start\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\"\n\n # Backup de la VM 100 al storage 'pbs-main'\n vm_100_backup:\n url: https://pve.local:8008/api/vms/100/backup\n method: POST\n content_type: 'application/json'\n payload: '{\"storage\": \"pbs-main\", \"mode\": \"snapshot\", \"compress\": \"zstd\"}'\n headers:\n Authorization: \"Bearer !secret proxmenux_token\""
},
"health": {
"heading": "Monitor de salud",
"rows": [