homelab: Speicherpool, NAS und Sicherungen überwachen – mit Empfehlungen, was Platz bringt
User-Wunsch 25.09.: Speicherpool im Wächter (gelb ab 80 %, rot bei 10 % frei) samt Empfehlungen, dazu das NAS (Backup-Ziel, per NFS auf dem Proxmox-Host). - Ausführer: Thin-Pools mit echter Belegung je Volume (lvs), ungenutzte und verwaiste Platten, VM-Belegung über den Gast-Agenten, Discard je VM, Netzlaufwerke (df mit Zeitlimit, hängender harter NFS-Mount hält nichts auf), Sicherungsaufträge und jüngste Sicherung je Gast. - Homelab-Teil: services/homelab/speicher.py (Auswertung, Empfehlungen, Wächter pruefe_speicher, NAS-Erreichbarkeit per TCP), GET /api/homelab/speicher; Gast-Plattenwächter nennt jetzt auch VMs richtig. - Oberfläche: Karte „Speicher und Sicherungen“ im Homelab-Cockpit. - deploy.sh und ausfuehrer-einrichten.sh warten, solange im Homelab ein Update oder „Alle aktualisieren“ läuft (der Neustart bräche den Lauf ab). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
9867affc5a
commit
903fbbfbb9
@@ -10,7 +10,7 @@ import { melden } from "./meldungen"
|
||||
import { stromVerbunden } from "./strom"
|
||||
import type {
|
||||
AktionsErgebnis, Altrest, AufraeumKandidat, BoxMesswerte, EinstellungenStand, Hinweis, HomelabEinstellungen,
|
||||
HomelabLauf, HomelabMesswerte, HomelabStand, Instanz, InstanzMitStand, Job, Modell, Nutzung, PartnerStatus,
|
||||
HomelabLauf, HomelabMesswerte, HomelabSpeicher, HomelabStand, Instanz, InstanzMitStand, Job, Modell, Nutzung, PartnerStatus,
|
||||
ProtokollEintrag, Radar, SammelPlanSchritt, Sammellauf, Sicherung, Start, TelegramTest, UpdateDetails, ZielAktion,
|
||||
ZielStand, Zeitraum,
|
||||
} from "./typen"
|
||||
@@ -423,6 +423,16 @@ export const useHomelabProtokoll = (aktiv: boolean, berichte: boolean) =>
|
||||
retry: false,
|
||||
})
|
||||
|
||||
/** Speicherpool, NAS und Sicherungen samt Empfehlungen — der Bericht dahinter kommt alle 10 Minuten. */
|
||||
export const useHomelabSpeicher = (aktiv: boolean) =>
|
||||
useQuery({
|
||||
queryKey: ["homelab-speicher"],
|
||||
queryFn: () => api<HomelabSpeicher>("/api/homelab/speicher"),
|
||||
enabled: aktiv,
|
||||
refetchInterval: takt(60_000),
|
||||
retry: false,
|
||||
})
|
||||
|
||||
export const useHomelabEinstellungen = (aktiv: boolean) =>
|
||||
useQuery({
|
||||
queryKey: ["homelab-einstellungen"],
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import type { SpeicherStufe, SicherungsLage } from "@/lib/typen"
|
||||
|
||||
// Speicher und Sicherungen des Homelabs (seit 25.09.2026): die kleinen Texte der Karte im Homelab-Cockpit.
|
||||
|
||||
const komma = (n: number, stellen = 1) => n.toFixed(stellen).replace(".", ",")
|
||||
|
||||
/** „184 GB“, „5,2 GB“, „2,3 TB“ — ab 10 GB ohne Nachkommastelle. */
|
||||
export function groesse(bytes: number | null | undefined): string {
|
||||
if (bytes === null || bytes === undefined) return "–"
|
||||
if (bytes >= 1e12) return `${komma(bytes / 1e12)} TB`
|
||||
return bytes >= 10e9 ? `${Math.round(bytes / 1e9)} GB` : `${komma(bytes / 1e9)} GB`
|
||||
}
|
||||
|
||||
/** Der Zeitplan eines Sicherungsauftrags in Worten: „02:30“ heißt bei Proxmox täglich um 02:30. */
|
||||
export function zeitplanText(zeitplan: string | null): string {
|
||||
if (!zeitplan) return "ohne Zeitplan"
|
||||
return /^\s*\d{1,2}:\d{2}\s*$/.test(zeitplan) ? `täglich ${zeitplan.trim()}` : `Zeitplan „${zeitplan}“`
|
||||
}
|
||||
|
||||
/** „täglich 02:30 auf pbs-qnap“ — alle Aufträge in einer Zeile. */
|
||||
export function auftraegeText(s: SicherungsLage): string {
|
||||
if (s.jobs.length === 0) return "Kein Sicherungsauftrag in Proxmox"
|
||||
return s.jobs.map((j) => `${zeitplanText(j.zeitplan)} auf ${j.speicher ?? "?"}`).join(", ")
|
||||
}
|
||||
|
||||
export const STUFE_TEXT: Record<SpeicherStufe, string> = { ok: "in Ordnung", gelb: "wird knapp", rot: "fast voll" }
|
||||
@@ -461,3 +461,59 @@ export interface HomelabEinstellungen {
|
||||
ausfuehrer: { verbunden: boolean; zuletzt: number | null; nur_lesen: boolean; sicherung_speicher: string | null }
|
||||
}
|
||||
|
||||
|
||||
// --- Speicher und Sicherungen des Homelabs (seit 25.09.2026) -------------------------------------------------
|
||||
|
||||
export type SpeicherStufe = "ok" | "gelb" | "rot"
|
||||
|
||||
export interface SpeicherPool {
|
||||
speicher: string
|
||||
belegt: number
|
||||
gesamt: number
|
||||
frei: number
|
||||
anteil: number
|
||||
meta_anteil: number | null
|
||||
aktiv: boolean
|
||||
stufe: SpeicherStufe
|
||||
}
|
||||
|
||||
export interface NasStand {
|
||||
server: string | null
|
||||
ziel: string
|
||||
quelle: string | null
|
||||
art: string
|
||||
eingebunden: boolean
|
||||
zustand: "ok" | "haengt" | "fehler" | null
|
||||
erreichbar: boolean | null
|
||||
belegt: number | null
|
||||
gesamt: number | null
|
||||
anteil: number | null
|
||||
stufe: SpeicherStufe
|
||||
problem: string | null
|
||||
}
|
||||
|
||||
export interface SicherungsLage {
|
||||
jobs: { zeitplan: string | null; speicher: string | null; alle: boolean }[]
|
||||
ziele: { speicher: string; art: string | null; aktiv: boolean | null; belegt: number | null; gesamt: number | null }[]
|
||||
erfasst: number
|
||||
fehlend: { ziel: string; name: string; zuletzt: number | null }[]
|
||||
zuletzt: number | null
|
||||
probleme: string[]
|
||||
stufe: SpeicherStufe | "keine"
|
||||
}
|
||||
|
||||
export interface SpeicherEmpfehlung {
|
||||
art: "trim" | "trim-vm" | "ungenutzt" | "verwaist" | "snapshot"
|
||||
titel: string
|
||||
text: string
|
||||
kurz: string
|
||||
platz: number | null
|
||||
}
|
||||
|
||||
export interface HomelabSpeicher {
|
||||
bericht: boolean
|
||||
pools: SpeicherPool[]
|
||||
nas: NasStand[]
|
||||
sicherungen: SicherungsLage
|
||||
empfehlungen: SpeicherEmpfehlung[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user