Commit Graph
9 Commits
Author SHA1 Message Date
alientimandClaude Sonnet 5 c9ac0bf69b Lizenz-/Modulsystem Phase 1: TESM-seitiges Gating, Aktivierung, Topbar (v1.2.0)
Baut auf licensing.py (Phase 0) auf und schaltet TESM erstmals auf ein
lizenziertes Modulmodell um. Standard-Funktionen (Dashboard, Clients,
Switche, Zugangsdaten, Benutzer, Gruppen, Auditlog, Live-Log, Verlauf,
Import) bleiben immer frei nutzbar.

- license_active()/module_licensed()-Gate-Funktionen + In-Memory-
  Lizenzcache (_load_license, _write_license_file, _delete_license_file),
  Jinja-Globals fuer Templates.
- Vollstaendige Module (DHCP inkl. Kea-Log, Fileshare, Wartung) werden ohne
  passendes Modul in der Lizenz komplett aus der Navigation ausgeblendet
  (_nav_key_visible) UND serverseitig auf Routenebene abgewiesen
  (_require_module) -- ein direkter URL-Aufruf hilft nicht.
- 'Sichtbar, aber ohne Lizenz inaktiv': LDAP- und NGINX-Einstellungen,
  Papierkorb-Bearbeiten, Export sowie das Pruefintervall-Feld (aus dem
  gemeinsamen Systemeinstellungen-Gate herausgeloest, Hostname/Zeitzone/
  Netzwerk/Logs bleiben frei) zeigen ohne Lizenz einen Hinweis statt der
  Aktion.
- Export bleibt als bewusste Ausnahme auch im lizenzlosen Zustand nutzbar,
  wenn dieser durch eine selbst ausgeloeste Deaktivierung (Systemwechsel)
  entstanden ist (license_export_grace).
- Automatischer PoE-Neustart bei Ausfall wird in poe.sh (nicht in Python)
  gegatet -- einmal pro Schleifendurchlauf gelesen, an check_device()
  durchgereicht; der manuelle Neustart-Button (devices.restart) bleibt
  komplett unangetastet.
- Topbar-Lizenzanzeige (Prioritaet: fehlt > abgelaufen > laeuft in <=30
  Tagen ab > Heartbeat seit >=14 Tagen ausgeblieben (rein informativ) >
  alles ok), eigene CSS-Blink-Varianten fuer Rot/Orange (die vorhandene
  pulse-dot-Animation war fest auf Gruen verdrahtet).
- Neue Settings-Unterseite 'Lizenz': Status, Lizenzdatei-Upload, Online-
  Aktivierung/-Deaktivierung mit automatischem Fallback auf einen manuell
  auszutauschenden Code (ein Protokoll, zwei Transportwege, siehe
  licensing.py), Anbieter-Kontaktkarte.
- 6-stuendiger Heartbeat-Hintergrundthread (_license_heartbeat_loop, exakt
  nach dem Vorbild von _audit_archive_loop).

Isoliert auf dem Testsystem (192.168.82.51) verifiziert: alle fuenf
Topbar-/Sichtbarkeitszustaende (keine/gueltige/bald ablaufende/abgelaufene/
heartbeat-stale Lizenz) per Playwright durchgespielt, kompletter Online-
Fallback-auf-Offline-Code-Austausch fuer Aktivierung UND Deaktivierung
gegen einen simulierten Master erfolgreich durchlaufen (inkl. Export-
Grace-Ausnahme nach Deaktivierung).

Bewusst NICHT nach main gemergt/getaggt/ausgerollt: ohne den in Phase 2
noch zu bauenden Master-Lizenzserver kann POETEST noch keine echte Lizenz
beziehen -- ein Rollout jetzt wuerde dort DHCP/Fileshare/Wartung/LDAP/
NGINX/Papierkorb/Export/automatischen Neustart sofort abschalten. Bleibt
auf dev, bis Phase 2 (Master) + Phase 3 (POETEST-Enterprise-Lizenz) so
weit sind, dass beides zusammen ausgerollt werden kann.

Teil des Lizenz-/Modulsystems, siehe Plan toasty-twirling-hickey.md
(Phase 1 von 3).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 00:45:35 +02:00
alientim 33753e4f41 Erklärende Kommentare aus dem Code entfernt, in KNOWLEDGE_BASE.md überführt
Betrifft app.py, create_db.py, poe.sh sowie alle HTML-Templates mit
Kommentaren (Jinja {# #}, HTML <!-- -->, eingebettetes JavaScript //).
Docstrings bleiben unangetastet -- nur reine Kommentarzeilen/-fragmente
wurden entfernt, damit der Code selbst schlank bleibt, ohne die
dahinterliegende Begründung zu verlieren.

Umsetzung:
- app.py/create_db.py: per Pythons eigenem tokenize-Modul entfernt (sicher
  gegen '#' innerhalb von String-Literalen, Shebang-Zeile ausgenommen).
- poe.sh: manuell, da einzelne expect-Prompt-Strings ('expect "#"')
  ein literales '#' als Teil des Strings enthalten, kein Kommentar.
- Templates: {# #}/<!-- --> per Regex (eindeutige Delimiter, anschließend
  mit Jinja2s eigenem Parser validiert), echte // -JS-Kommentare manuell
  identifiziert (zwei Fundstellen mit '//' waren tatsächlich Code --
   als Protocol-relative-URL-Template-
  String -- und wurden bewusst nicht angefasst).

Verifiziert: alle Python-/Bash-/Jinja-Dateien syntaktisch weiterhin
gültig, live auf der Testbox deployt und alle 14 Kernrouten mit 200
bestätigt, keine Fehler im App-Log.
2026-08-14 12:05:39 +02:00
alientim c55f9d992d poe.sh: Regression bei ArubaOS-Manager-Accounts zurückgesetzt
disable_poe()/enable_poe() waren waehrend dieser Sitzung um explizite
'timeout { exit 1 }'/'eof { exit 1 }'-Abbrueche 'gehaertet' worden, um
echte SSH-/Kommando-Fehlschlaege vom Aufrufer unterscheidbar zu machen.

Live an Switch 'ST-2000-Sued' (Aruba JL322A 2930M) reproduziert: das
dafuer verwendete Login-Prompt-Pattern -re ".*> $" matcht nur einen
Operator-Prompt ("switchname>"). Landet der SSH-Account (hier: admin)
nach dem Login mit Manager-Rechten direkt im privilegierten Modus
("switchname#"), matcht das Pattern nie -> 5s-Timeout -> exit 1,
obwohl Passwort und Verbindung tatsaechlich in Ordnung waren. Jeder
manuelle wie automatische PoE-Neustart ueber einen Manager-Account
schlug dadurch fehl.

disable_poe()/enable_poe() sind jetzt wieder exakt auf den Stand der
urspruenglichen, in Produktion ueber Jahre bewaehrten Fassung
zurueckgesetzt (keine expliziten timeout/eof-Abbrueche, kein
abschliessendes exit 0) -- nur der Kommentar wurde aktualisiert, um
diesen Vorfall zu dokumentieren.
2026-08-13 23:25:55 +02:00
alientim 51d105399b Kritischen poe.sh-Pfadbug beheben + verschachteltes <form> in Wartung fixen
- KRITISCH: usr/local/bin/custom/poe.sh wurde bei der TESM-Umbenennung
  übersehen und zeigte weiterhin komplett auf die alten Pfade
  (/srv/poe_manager/sqlite.db, /srv/poe_manager/generate_ips.py,
  /var/log/poe-manager) -- der Ping-Check/PoE-Neustart-Loop
  (tesm-check.service) lief dadurch seit dem Umzug nur noch auf Fehler
  ("No such file or directory"), das Live-Log stand seit gestern 19 Uhr
  still und automatische PoE-Neustarts bei Geräteausfall liefen die
  ganze Zeit ins Leere. Auf POETEST live behoben und verifiziert: Log
  schreibt wieder frische Einträge, Checks laufen wieder durch.
- Wartung: "Update starten" nahm live IMMER zusätzlich das erste Gerät
  mit, auch ganz ohne angehakte Checkbox. Ursache: der "Neustart"-Button
  jeder Zeile saß in einem eigenen <form>, das INNERHALB des großen
  #updateForm verschachtelt war -- ungültiges HTML, wodurch Browser das
  äußere Formular vorzeitig schließen/aufspalten. Behoben, indem jedes
  Neustart-<form> jetzt außerhalb von #updateForm steht und der Button
  es nur per form="reboot-<mac>" referenziert. Live verifiziert: ein
  gezielt einzeln ausgewähltes Gerät startet jetzt ausschließlich sich
  selbst, keine leere Auswahl mehr möglich.
- Zusätzlich defensiv: Checkboxen werden beim Laden der Wartungsseite
  jetzt explizit zurückgesetzt (manche Browser stellen den
  Checked-Zustand nach einem Redirect/Reload sonst aus dem Verlauf
  wieder her).
- Restliche "poe"-Relikte aus der TESM-Umbenennung bereinigt: Export-
  Dateiname (poe_manager_export_… → tesm_export_…), Kommentare
  (poe_web.service → tesm.service) sowie ein für den Nutzer sichtbarer
  Hinweistext in Systemeinstellungen (rpi-check.service → tesm-check.service).
2026-08-13 15:54:40 +02:00
alientimandClaude Sonnet 5 7b30ebce7b Logging & Log-Rotation, Zeitzone, Dashboard-UX, Design-Politur
Logging-Infrastruktur (Logs können nach einem Import mit vielen Geräten
schnell vollaufen):
- Vier eigene, rotierte Log-Dateien statt allem in /var/log vermischt:
  Live (poe.sh, jetzt eine einzige durchgehend fortgeschriebene Datei
  statt vorher ein neues rpi-<timestamp>.log pro Dienst-Neustart),
  Änderungen (Spiegel der audit_log-Tabelle), App (Flask-Fehler/
  Warnungen, vorher nur im journalctl-Output), Kea-DHCP (eigene
  Logging-Konfiguration in der generierten kea-dhcp4.conf)
- Kea-DHCP-Log bewusst NICHT im gemeinsamen Verzeichnis: Keas
  AppArmor-Profil erlaubt Schreibzugriff exklusiv auf
  /var/log/kea/kea-dhcp4.log (kein Verzeichnis-Wildcard) -- live als
  "DENIED ... mknod ... .lock" reproduziert; die App nutzt Keas eigenen,
  bereits erlaubten Pfad statt das AppArmor-Profil eines Systemdienstes
  aufzuweichen. logrotate deckt trotzdem beide Verzeichnisse mit einer
  Regel ab
- Neue Log-Seite "Kea-DHCP" (Logs-Bereich, eigenes Recht logs_kea.view)
- Rotation (Intervall täglich/wöchentlich/monatlich, Aufbewahrung als
  Anzahl Rotationen) unter Systemeinstellungen → Logs einstellbar,
  generiert /etc/logrotate.d/poe-manager; copytruncate, da keiner der
  drei schreibenden Prozesse ein Reopen-Signal implementiert
- Einmalige Migration räumt alte, verwaiste rpi-*.log-Dateien auf

Zeitzone (Systemeinstellungen, mit Hostname in einer Kachel "Host"):
setzt die System-Zeitzone per timedatectl, damit Logs/Änderungsverlauf
die tatsächliche lokale Zeit statt UTC zeigen. time.tzset() direkt nach
dem Setzen lässt die bereits laufende poe_web.service-Instanz die neue
Zeitzone sofort übernehmen, ohne Neustart.

Systemeinstellungen neu sortiert: Host + Netzwerkeinstellungen (beide
Host-Konfiguration) nebeneinander, dann Logs, dann Prüfintervall.

Netzwerkeinstellungen: DNS-Anzeige zeigte bisher den lokalen
systemd-resolved-Stub (127.0.0.53) aus /etc/resolv.conf statt der
echten Server -- jetzt über "resolvectl dns <interface>", inkl. Fix
für eine falsch geparste IPv6-Fortsetzungszeile ohne Label, und
gefiltert auf IPv4 (diese Seite verwaltet nur IPv4-Konfiguration, per
IPv6-Router-Advertisement gelernte Server sind hier irreführend).

Dashboard: die vier Stat-Kacheln (Online/Offline/Deaktiviert/Gesamt)
sind jetzt klickbare Filter (blenden alle anderen Abschnitte aus, Klick
auf die aktive Kachel oder "Gesamt" hebt den Filter auf); jeder
Abschnitt lässt sich unabhängig davon per Klick auf seinen Titel ein-/
ausklappen. Beide Zustände bleiben über die automatischen Live-Updates
hinweg erhalten.

Design-Politur:
- Hauptinhaltsbereich nutzt jetzt die volle verfügbare Breite (kein
  Bootstrap-typisches festes max-width mehr) -- Modals bleiben bewusst
  bei ihrer kompakten, festen Breite
  Akzentfarbe exakt auf das Orange aus dem WiS-Logo abgestimmt
  (#ff7100, per Pixel-Sampling ermittelt) statt einer nur ähnlichen,
  frei gewählten Nuance
- Abmelden führt zurück auf das (auch ohne Login einsehbare) Dashboard
  statt auf die Login-Seite

Live gegen die echte Test-VM verifiziert: alle vier Logs werden
geschrieben, logrotate-Konfiguration korrekt generiert, ein
Zeitzonenwechsel (UTC → Europe/Berlin) wirkte sofort, DNS-Anzeige zeigt
jetzt die echten IPv4-Server (1.1.1.1, 8.8.8.8) statt Stub/IPv6,
Dashboard-Filter/-Collapse und Logout-Redirect per Playwright bestätigt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 13:30:56 +02:00
alientimandClaude Sonnet 5 d525ef2e0a poe.sh: parallele Geräte-Prüfung + echte PoE-Erfolgskontrolle
Nach einem echten Import (46 Geräte, 8 Switche aus dem Altsystem)
zeigten sich zwei Probleme in der Hintergrund-Prüfschleife:

- Geräte wurden strikt sequentiell geprüft (eine einzige "while read"-
  Schleife) -- ein einzelnes ausgefallenes Gerät mit ebenfalls nicht
  erreichbarem Switch (bis zu 5s expect-Timeout je Verbindungsschritt)
  verzögerte die Prüfung aller nachfolgenden Geräte. Jede Geräte-Prüfung
  läuft jetzt als eigener Hintergrund-Job (& + wait), über Process
  Substitution statt einer Pipe, damit wait die Jobs auch tatsächlich
  erfasst (bei "cmd | while ...; done" liefe die Schleife sonst in
  einer eigenen Subshell).
- disable_poe()/enable_poe() haben unabhängig vom tatsächlichen Ergebnis
  der SSH/expect-Sitzung immer wie ein Erfolg gewirkt -- lief die
  Verbindung in einen Timeout (Switch nicht erreichbar, falsche
  Zugangsdaten, falscher Port), endete das expect-Skript trotzdem mit
  Exit-Code 0, poe.sh loggte fälschlich "PoE deaktiviert"/"PoE
  aktiviert", obwohl am Switch nichts passiert war. Jeder kritische
  expect-Schritt hat jetzt einen eigenen timeout-Zweig mit explizitem
  "exit 1"; poe.sh wertet den Rückgabewert aus und loggt bei einem
  nicht erreichbaren/ablehnenden Switch stattdessen klar, dass die
  PoE-Aktion fehlgeschlagen ist. Gilt für die Prüfschleife, den
  manuellen Neustart (poe.sh restart <mac>) und damit auch den
  Dashboard-Neustart-Button.

Live verifiziert: alle 46 Geräte innerhalb von ~2s geprüft (statt
sequentiell), alle 43 offline erkannten Geräte mit Switch-Zuordnung
zeigten korrekt die neue Fehlermeldung, da die realen Switch-IPs vom
Test-Host aus nicht erreichbar sind -- vorher hätte das fälschlich als
43x "PoE deaktiviert/aktiviert" geloggt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-12 11:59:52 +02:00
alientimandClaude Sonnet 5 06db4c1382 Switche: optionaler SSH-Port statt fest 22
- Neue Spalte switches.ssh_port (nullable INTEGER), Migration für
  bestehende DBs in _ensure_schema(), Feld in create_db.py ergänzt.
- Formular (Anlegen/Bearbeiten): optionales SSH-Port-Feld, Validierung
  1-65535, leer -> NULL (= Standard 22 überall, SWITCH_DEFAULT_SSH_PORT).
  Switch-Liste zeigt den effektiven Port inkl. "(Standard)"-Hinweis.
- generate_ips.py liefert den effektiven Port (Fallback 22) als eigenes
  Pipe-Feld an poe.sh; poe.sh übernimmt es in disable_poe/enable_poe und
  reicht es als "ssh -p <port>" an die expect-Skripte durch (Default
  weiterhin 22 falls Parameter fehlt).
- Web-Terminal (Verbindungstest) sendet den im Formular eingetragenen
  Port statt hartkodiert 22.
- Live getestet: gültiger/leerer/ungültiger Port beim Anlegen, korrekte
  Weitergabe durch generate_ips.py inkl. Feldreihenfolge, die poe.sh
'read' erwartet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 19:56:23 +02:00
alientimandClaude Sonnet 5 e4cceb4091 poe.sh: CRLF-Zeilenenden, Feldanzahl und Switch-Gating fixen
- Datei hatte CRLF-Zeilenenden (vermutlich aus einer Windows-Bearbeitung),
  wodurch das Skript unter Linux/WSL mit "command not found: $'\r'" und
  Syntaxfehlern abbrach. Auf LF normalisiert.
- Die Haupt-Check-Schleife las per `read` nur 7 Felder aus
  generate_ips.py, das aber inzwischen 8 Felder liefert (MAC am Ende
  angehängt) — dadurch landete die MAC-Adresse an $switch_pass
  angehängt. `mac` als zusätzliche (ungenutzte) read-Variable ergänzt.
- PoE-Neustart wurde bei nicht erreichbaren Geräten ausgelöst, sobald ein
  `port`-Wert gesetzt war — unabhängig davon, ob dem Gerät überhaupt ein
  Switch zugeordnet ist. Das führte zu sinnlosen SSH-Versuchen mit leeren
  Zugangsdaten (ssh @) und irreführenden "PoE deaktiviert/aktiviert"
  Log-Einträgen für Geräte ohne Switch. Prüft jetzt zusätzlich, dass
  switch_ip nicht leer ist, bevor ein Neustart versucht wird (gilt für
  den regulären Check-Loop und den manuellen Neustart).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 14:56:53 +02:00
alientimandClaude Sonnet 5 82bfeb17ed Initial commit: PoE Manager modern UI rebuild
- Neues, eigenständiges Frontend (Sidebar, zentriertes Logo in der Topbar,
  Dark/Light-Theme, Karten-Dashboard, Toasts/Modals statt Bootstrap)
- Oeffentliches Kurz-Dashboard ohne Login (Status-Uebersicht)
- Browser-SSH-Terminal (paramiko, plattformunabhaengig) zum Testen von
  Switch-Zugangsdaten inkl. interaktiver Host-Key-Bestaetigung
- Granulares Rechtesystem mit Gruppen (Devices/Switches-Berechtigungen)
- Aufgeraeumtes Backend mit konfigurierbaren Pfaden, auto-generierten
  Secrets statt hart codierter Werte im Original

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-10 12:18:49 +02:00