DHCP: manuelle Reservierungen, Options-Schutz+Dropdown-UI, Lease-Countdown-Fix

1. Manuelle Reservierungen (dhcp_manual_reservations) fuer Geraete, die
   nicht als Client in dieser App gepflegt werden -- bewusst eine eigene,
   explizite Aktion (MAC/IP/Name), damit kein externes Geraet unueberwacht
   automatisch eine feste IP bekommt. _dhcp_reservation_candidates fuehrt
   automatische (aus devices) und manuelle Reservierungen jetzt zusammen,
   case-insensitiv nach MAC dedupliziert (automatisch gewinnt bei Konflikt).
   Automatische Reservierungen sind in der Tabelle nicht loeschbar
   (Schloss-Symbol statt Button, sie entstehen/verschwinden mit den
   Client-Stammdaten), manuelle schon. Live verifiziert: Hinzufuegen,
   doppelte MAC ablehnen, ungueltige MAC ablehnen, generierte Kea-Config
   mit gemischten Auto-/manuellen Reservierungen besteht kea-dhcp4 -t.

2. Standard-DHCP-Optionen um 10 weitere verifizierte Optionen erweitert
   (u.a. host-name/12 -- Kea-Name mit Bindestrich, NICHT "hostname", live
   gegen echtes Kea geprueft) -- jetzt 57 insgesamt. Standard-Optionen sind
   nicht mehr loeschbar (Backend lehnt es ab, UI zeigt ein Schloss-Symbol
   statt Loeschen-Button) -- vorher liess sich eine vorbefuellte Options-
   Definition versehentlich entfernen.

3. Options-Tabellen (global UND pro Reservierung) zeigen jetzt nur noch
   tatsaechlich genutzte Options -- eigene immer, Standard-Optionen nur mit
   gesetztem Wert. Weitere Standard-Optionen kommen ueber ein Dropdown
   "+ Option hinzufuegen" dazu statt permanent alle 57 als leere Felder zu
   zeigen. Das neu eingeblendete Feld wird automatisch in den sichtbaren
   Bereich gescrollt und fokussiert (bei bis zu 57 moeglichen Optionen kann
   das Feld sonst weit unterhalb des sichtbaren Modal-Ausschnitts liegen
   und es wirkt so, als waere nichts passiert).

4. Lease-Countdown-Fix: die Ablaufzeit wird jetzt explizit als UTC
   ausgewiesen (Kea arbeitet intern in UTC-Epoch) und zusaetzlich als live
   tickender Countdown angezeigt (gleiches Prinzip wie der bestehende
   "Naechste Pruefung"-Timer). Vorher wirkte eine reine Absolutzeit auf der
   nicht selbst aktualisierenden Seite bei den kurzen Standard-Lease-Zeiten
   (600s) schnell "schon abgelaufen", sobald etwas Zeit vergangen war, bis
   man tatsaechlich hinschaut -- live im echten Betrieb genau als dieses
   Missverstaendnis beobachtet und anhand der rohen Kea-CSV verifiziert,
   dass die richtige Spalte (expire) korrekt gelesen wird.

5. UI-Feinschliff: "In Datei schreiben" bei den Reservierungen heisst jetzt
   "Speichern" und ist der primaere (orange) Button, "Reservierung
   hinzufuegen" sekundaer -- das Hinzufuegen legt nur einen Datensatz an,
   erst "Speichern" schreibt die tatsaechlich wirksame Kea-Config.

Alles live auf der Test-VM deployt und verifiziert (Playwright fuer die
Dropdown-Sichtbarkeit/Fokus-Interaktion, curl fuer die Backend-Validierung,
kea-dhcp4 -t fuer die generierte Konfiguration), keine Fehler im
journalctl-Log.
This commit is contained in:
2026-08-11 15:52:52 +02:00
parent 9885a579ea
commit 1a0b55ed44
5 changed files with 371 additions and 77 deletions
+60 -37
View File
@@ -271,45 +271,70 @@ der aktiv weiterentwickelte Nachfolger und bildet „globaler Wert, pro Client
kein "ungültig", da das Fehlen des Netzes hier Absicht ist), statt es
jedes Mal neu anlegen zu müssen.
- **DHCP-Options** (`dhcp_option_defs`/`dhcp_option_values`): eine kuratierte
Auswahl an **47 Standard-Optionen** (analog den „Vordefinierten Optionen“
eines Windows-DHCP-Servers — z.B. NTP-/WINS-/TFTP-/SMTP-Server, Boot-Datei,
Domain-Search, IP-Forwarding) ist automatisch vorbefüllt; Router/DNS-Server/
Domain-Name/Lease-Zeiten sind bewusst ausgenommen, da dafür bereits eigene,
dedizierte Felder existieren (Subnetze bzw. globale Einstellungen oben).
Alle 47 Namen sind live gegen eine echte Kea-2.4.1-Instanz verifiziert
(`kea-dhcp4 -t`, jede Option einzeln getestet). Standard-Optionen bekommen
bewusst **kein eigenes `option-def`** in der generierten Konfiguration —
Kea kennt sie bereits nativ, eine Neudefinition würde die eingebaute
duplizieren; nur zusätzlich angelegte, wirklich eigene/herstellerspezifische
Options (z.B. eine Terminal-Boot-URL) bekommen eines. Beide Arten
funktionieren im UI identisch: Code, Name, Kea-Datentyp und Beschreibung
frei definierbar, jede Option hat einen **globalen** Wert sowie optional
einen **Wert pro Client** — ein Client-Override überschreibt den globalen
Wert ausschließlich für dieses eine Gerät (technisch: globale Werte landen
im Top-Level `option-data`, Overrides im `option-data` der jeweiligen
Kea-Reservierung, was Kea automatisch pro Client Vorrang geben lässt).
Ein versehentlich vom Admin gelöschter Standard-Eintrag wird nach einem
Neustart nicht automatisch wieder angelegt (einmalige Migration, kein
Zurückschreiben bei jedem Start).
- **Reservierungen**: für jedes aktive Gerät mit gültiger MAC + IP wird eine
Kea-Reservierung im **passenden Subnetz** erzeugt (die IP entscheidet, zu
welchem der ggf. mehreren konfigurierten Subnetze ein Gerät gehört); der
Hostname wird aus dem Gerätenamen abgeleitet (nur `a-z0-9-`, Kollisionen
Auswahl an **57 Standard-Optionen** (analog den „Vordefinierten Optionen“
eines Windows-DHCP-Servers — u.a. Hostname erzwingen, NTP-/WINS-/TFTP-/
SMTP-Server, Boot-Datei, Domain-Search, IP-Forwarding) ist automatisch
vorbefüllt und **nicht löschbar** (Backend lehnt es ab, UI zeigt statt
eines Löschen-Buttons ein Schloss-Symbol) — Router/DNS-Server/Domain-Name/
Lease-Zeiten sind bewusst ausgenommen, da dafür bereits eigene, dedizierte
Felder existieren (Subnetze bzw. globale Einstellungen oben); ebenso
client-/protokollinterne Optionen (message-type, parameter-request-list,
requested-address, ...), die serverseitig nicht sinnvoll setzbar sind.
Alle 57 Namen sind live gegen eine echte Kea-2.4.1-Instanz verifiziert
(`kea-dhcp4 -t`, jede Option einzeln getestet — u.a. „host-name“ mit
Bindestrich statt „hostname“ als Kea-Name richtiggestellt). Standard-
Optionen bekommen bewusst **kein eigenes `option-def`** in der generierten
Konfiguration — Kea kennt sie bereits nativ, eine Neudefinition würde die
eingebaute duplizieren; nur zusätzlich angelegte, wirklich eigene/
herstellerspezifische Options (z.B. eine Terminal-Boot-URL) bekommen eines
und bleiben frei löschbar.
In der Tabelle sind grundsätzlich nur **tatsächlich genutzte** Options
sichtbar (eigene immer, Standard-Optionen nur mit gesetztem globalen Wert)
— weitere Standard-Optionen kommen über ein Dropdown „+ Standard-Option
hinzufügen“ dazu, statt alle 57 dauerhaft als leere Zeilen anzuzeigen.
Jede Option hat einen **globalen** Wert sowie optional einen **Wert pro
Client** — ein Client-Override überschreibt den globalen Wert
ausschließlich für dieses eine Gerät (technisch: globale Werte landen im
Top-Level `option-data`, Overrides im `option-data` der jeweiligen
Kea-Reservierung, was Kea automatisch pro Client Vorrang geben lässt). Im
Reservierungs-Options-Dialog gilt dasselbe Prinzip: nur Options mit
gesetztem Override sind sichtbar, weitere kommen über ein Dropdown dazu
(das neu eingeblendete Feld wird automatisch in den sichtbaren Bereich
gescrollt und fokussiert).
- **Reservierungen aus zwei Quellen**: automatisch für jedes aktive Gerät mit
gültiger MAC + IP (Client-Stammdaten dieser App) sowie zusätzlich **manuell
anlegbar** („Reservierung hinzufügen“, MAC/IP/Name) — für Geräte, die
nicht als Client gepflegt werden (z.B. ein externes Gerät), sodass ihnen
bewusst und mit voller Kontrolle eine feste IP gegeben werden kann, statt
sie unüberwacht automatisch anzubinden. Automatische Reservierungen können
in dieser Tabelle **nicht gelöscht** werden (Schloss-Symbol statt Button —
sie entstehen/verschwinden mit den Client-Stammdaten), manuelle schon. Bei
einer MAC in beiden Quellen gewinnt immer die automatische. Jede
Reservierung wird ins **passende Subnetz** einsortiert (die IP entscheidet,
zu welchem der ggf. mehreren konfigurierten Subnetze sie gehört); der
Hostname wird aus dem Namen abgeleitet (nur `a-z0-9-`, Kollisionen
innerhalb desselben Subnetzes bekommen automatisch ein `-2`/`-3`-Suffix).
Gete ohne MAC/IP oder mit einer IP außerhalb aller konfigurierten
Eintge ohne MAC/IP oder mit einer IP außerhalb aller konfigurierten
Subnetze werden mit Hinweis übersprungen — Kea lehnt eine Reservierung
außerhalb ihres Subnets als Konfigurationsfehler ab (mit einer echten
Kea-Instanz verifiziert).
Kea-Instanz verifiziert, inkl. einer Mischung aus automatischer und
manueller Reservierung im selben Subnetz).
- **Aktive Leases**: eigene Karte, liest die tatsächlich vergebenen Adressen
direkt aus Keas Lease-Datenbank (`kea-leases4.csv`, memfile-Backend —
kein Control-Agent nötig, reiner Lesezugriff auf die Datei). Zeigt damit
auch Clients **ohne eigene Reservierung**, die sich einfach eine freie IP
aus dem Pool genommen haben — deutlich als „Ohne Reservierung“ markiert,
statt nur die (unvollständige) Reservierungsliste zu zeigen.
- **Schreiben**: „In Datei schreiben (nur mit `settings_dhcp.edit`)
schreibt die vollständige, generierte Kea-JSON-Konfiguration an den
konfigurierten Ausgabepfad. Wirksam wird sie erst nach einem
Dienst-Neustart über den separaten Button.
statt nur die (unvollständige) Reservierungsliste zu zeigen. Die
Ablaufzeit wird explizit als **UTC** ausgewiesen (Kea arbeitet intern in
UTC-Epoch) und zusätzlich als live tickender Countdown angezeigt — eine
reine Absolutzeit auf einer nicht selbst aktualisierenden Seite wirkte bei
den kurzen Standard-Lease-Zeiten (600s) schnell „schon abgelaufen“, sobald
etwas Zeit vergangen war, bis man tatsächlich hinschaut (live auf der
Test-VM als genau dieses Missverständnis reproduziert).
- **Schreiben**: „Speichern“ bei den Reservierungen (nur mit
`settings_dhcp.edit`) schreibt die vollständige, generierte Kea-JSON-
Konfiguration an den konfigurierten Ausgabepfad. Wirksam wird sie erst
nach einem Dienst-Neustart über den separaten Button.
- **Ampel im Topbar**: neben dem Prüfintervall-Timer zeigt ein grüner/roter
Punkt, ob der Kea-Dienst läuft — nur sichtbar mit `settings_dhcp.view`.
- Reservierungen mit aktiven eigenen Options zeigen in der Tabelle, welche
@@ -331,12 +356,10 @@ Netzes (identischer `subnet`-CIDR, unterschiedliche Pools); ob Kea zwei
`subnet4`-Blöcke mit identischem `subnet`-Wert akzeptiert oder als Fehler
ablehnt, wurde nicht gegen eine echte Kea-Instanz geprüft — bei tatsächlich
unterschiedlichen Netzen (der eigentliche Anwendungsfall) besteht dieses
Risiko nicht. Die Leases-Anzeige wurde gegen eine echte (leere)
`kea-leases4.csv` verifiziert (korrektes Parsen, keine Endlos-/Absturz-
Fälle) — eine tatsächlich unreservierte Lease eines fremden Clients live
zu erzeugen und die „Ohne Reservierung“-Markierung damit End-to-End zu
zeigen, wurde nicht getestet (hätte einen echten, unkontrollierten
DHCP-Request auf dem gemeinsam genutzten Testnetz erfordert).
Risiko nicht. Die Leases-Anzeige wurde vollständig End-to-End im echten
Betrieb bestätigt: ein tatsächlicher, unreservierter Client im Testnetz
(„shellyhtg3-...“) hat sich selbstständig eine IP aus dem Pool geholt und
wurde korrekt mit der „Ohne Reservierung“-Markierung angezeigt.
## Netzwerkeinstellungen des Hosts (Systemeinstellungen)