Issue 1: finaler Agent-Job-Status

Management pollt jetzt offene Agent-Jobs und aktualisiert job_history mit:

  - finalem success / failed
  - Fehlertext
  - aktuellem/finalem Step
  - finishedAt
  - durationMs
  - Snapshot-ID aus den Agent-Logs, wenn ein Backup erfolgreich war

  Die Operations-Seite zeigt jetzt Dauer und Snapshot-ID.

  Issue 2: erweiterte Agent-Healthchecks
  /api/health am Agent prüft jetzt strukturiert:

  - fehlende Env-Konfiguration
  - Commands: incus, zfs, zpool, restic, udevadm, dd
  - ZFS Pool Existenz
  - ZFS Pool Capacity/Freespace via zpool list
  - /dev/zvol Zugriff
  - Restic Repository Zugriff
This commit is contained in:
Philipp
2026-05-21 10:27:04 +02:00
parent dc4989acfb
commit 87682a777f
8 changed files with 168 additions and 26 deletions
+10 -1
View File
@@ -31,13 +31,15 @@ export function Operations() {
</div>
{error ? <div className="rounded-md border border-red-900 bg-red-950/50 px-4 py-3 text-sm text-red-200">{error}</div> : null}
<Table
columns={['Time', 'Type', 'Node', 'VM', 'Status', 'Agent Job']}
columns={['Time', 'Type', 'Node', 'VM', 'Status', 'Duration', 'Snapshot', 'Agent Job']}
rows={history.map((row) => [
formatTime(row.startedAt),
row.type,
row.nodeName,
row.vmName,
row.error || row.status,
formatDuration(row.durationMs),
row.snapshotId || '-',
row.agentJobId || '-',
])}
title="Job History"
@@ -86,3 +88,10 @@ function formatTime(value) {
if (!value) return '-';
return new Intl.DateTimeFormat(undefined, { dateStyle: 'short', timeStyle: 'medium' }).format(new Date(value));
}
function formatDuration(value) {
if (!value) return '-';
const seconds = Math.round(Number(value) / 1000);
if (seconds < 60) return `${seconds}s`;
return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
}