forked from kay/RouterOS
Wizard: idempotenter WAN-Apply fuer DHCP-Client/PPPoE (Bug 21)
Wizard erneut auf einem Interface durchlaufen, das schon einen DHCP-Client hat (hier: aus einer zurueckgespielten Sicherung), scheiterte live mit "failure: dhcp-client on that interface already exists" - WanConfig.buildCommands() erzeugt fuer DHCP-Client/PPPoE immer .add, ohne vorher zu pruefen, ob auf dem Interface schon einer existiert. Fix: SetupViewModel.applyIdempotently faengt einen .add-Fehlschlag auf /ip dhcp-client bzw. /interface pppoe-client ab und wiederholt ihn als .set (nach "interface" gematcht) - bewusst nur fuer diese zwei Menues mit "maximal ein Eintrag pro Interface"-Semantik, nicht generell fuer jedes .add (z.B. /ip address erlaubt legitim mehrere Adressen pro Interface). Gefunden beim Versuch, M8 (Netzwerk-Isolation) live durchzutesten - dieser Test selbst ist noch nicht abgeschlossen, naechste Session dort weitermachen (siehe HANDOFF.md Naechste Schritte Punkt 1). HANDOFF.md/CHATLOG.md aktualisiert: Bug 21, Sessionende-Stand. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CTgRxJTzaQwaRkngbaE1GJ
This commit is contained in:
+20
@@ -676,3 +676,23 @@ Test, WLAN/Bonding/PPPoE-Live-Tests).
|
|||||||
- "ja, committen und beides aktualisieren" → dieser Eintrag, HANDOFF.md
|
- "ja, committen und beides aktualisieren" → dieser Eintrag, HANDOFF.md
|
||||||
(M14, Bug 20, Design-Durchgang, Dark-Mode-Bestätigung) aktualisiert,
|
(M14, Bug 20, Design-Durchgang, Dark-Mode-Bestätigung) aktualisiert,
|
||||||
Commit erstellt.
|
Commit erstellt.
|
||||||
|
|
||||||
|
## Session: M8-Hardware-Test begonnen (nicht abgeschlossen)
|
||||||
|
|
||||||
|
- "was steht als nächstes auf dem Plan?" → HANDOFF-Liste zusammengefasst.
|
||||||
|
"fangen wir bei 4 an" (M8 Netzwerk-Isolation) → per `AskUserQuestion`
|
||||||
|
geklärt: voller Wizard-Durchlauf statt nur gezieltem Firewall-Test,
|
||||||
|
kombiniert damit Punkt 1 (kompletter Wizard-Durchlauf) mit.
|
||||||
|
- Unterwegs zwei praktische RouterOS-Fragen beantwortet: ether5 aus der
|
||||||
|
Bridge entfernen (`/interface bridge port remove [find
|
||||||
|
interface=ether5]` bzw. Experte-Tab), dann "Unerwartete Antwort vom
|
||||||
|
Router: failure: dhcp-client on that interface already exists" beim
|
||||||
|
WAN-Schritt — Ursache: Wizard nutzt immer `.add`, aber auf dem
|
||||||
|
Interface existierte aus der zurückgespielten Sicherung schon ein
|
||||||
|
DHCP-Client. "fixe es gleich" → Bug 21, `SetupViewModel.
|
||||||
|
applyIdempotently` (Fallback auf `.set` bei `.add`-Fehlschlag auf
|
||||||
|
DHCP-Client/PPPoE), deployt.
|
||||||
|
- "ok, alles speichern, genug für heute" → dieser Eintrag, HANDOFF.md
|
||||||
|
(Bug 21, Nächste-Schritte Punkt 1 als "in Arbeit" markiert — der
|
||||||
|
eigentliche M8-Isolationstest ist noch nicht zu Ende geführt, nächste
|
||||||
|
Session dort fortsetzen) aktualisiert, Commit erstellt. Sitzung beendet.
|
||||||
|
|||||||
+34
-5
@@ -56,6 +56,17 @@ Farbwerte, alles adaptive System-Farben) — vom Nutzer live bestätigt.
|
|||||||
Release-Build unter `/Applications/RouterOS Assistant.app` ist auf
|
Release-Build unter `/Applications/RouterOS Assistant.app` ist auf
|
||||||
aktuellem Stand.
|
aktuellem Stand.
|
||||||
|
|
||||||
|
**Zum Sessionende:** M8-Hardware-Test (Netzwerk-Isolation) begonnen —
|
||||||
|
voller Wizard-Durchlauf über den Experte-Modus, WAN neu einrichten.
|
||||||
|
Dabei Bug 21 gefunden: der Wizard-Apply nutzte für WAN-DHCP-Client/PPPoE
|
||||||
|
immer `.add`, was auf einem bereits konfigurierten Interface (hier: aus
|
||||||
|
der zurückgespielten Sicherung) mit "failure: dhcp-client on that
|
||||||
|
interface already exists" scheiterte. Fix: `SetupViewModel.
|
||||||
|
applyIdempotently` versucht bei `.add` auf `/ip dhcp-client` oder
|
||||||
|
`/interface pppoe-client` nach einem Fehlschlag automatisch `.set`
|
||||||
|
(nach "interface" gematcht) — deployt, **aber der eigentliche
|
||||||
|
M8-Isolationstest selbst ist noch nicht zu Ende geführt/verifiziert**,
|
||||||
|
das ist der erste Schritt für die nächste Session.
|
||||||
## Ziel
|
## Ziel
|
||||||
|
|
||||||
Native macOS-App (SwiftUI), die Laien per geführtem Interview-Wizard durch
|
Native macOS-App (SwiftUI), die Laien per geführtem Interview-Wizard durch
|
||||||
@@ -378,6 +389,19 @@ erreichen (siehe Bug 1 unten).
|
|||||||
Singleton-Menü, nicht nur `/system routerboard` — der generische
|
Singleton-Menü, nicht nur `/system routerboard` — der generische
|
||||||
Lese-Pfad wird von Übersicht-, Geräte- und Experte-Tab gemeinsam
|
Lese-Pfad wird von Übersicht-, Geräte- und Experte-Tab gemeinsam
|
||||||
genutzt.
|
genutzt.
|
||||||
|
21. **Wizard-WAN-Apply war nicht idempotent** — Wizard erneut auf einem
|
||||||
|
Interface durchlaufen, das schon einen DHCP-Client hat (hier: aus
|
||||||
|
einer zurückgespielten Sicherung), scheiterte live mit "failure:
|
||||||
|
dhcp-client on that interface already exists". `WanConfig.
|
||||||
|
buildCommands()` erzeugt für DHCP-Client/PPPoE immer `.add`, ohne
|
||||||
|
vorher zu prüfen, ob auf dem Interface schon einer existiert. Fix:
|
||||||
|
`SetupViewModel.applyIdempotently` fängt einen `.add`-Fehlschlag auf
|
||||||
|
`/ip dhcp-client`/`/interface pppoe-client` ab und wiederholt ihn als
|
||||||
|
`.set` (nach "interface" gematcht) — bewusst nur für diese zwei
|
||||||
|
Menüs mit "maximal ein Eintrag pro Interface"-Semantik, nicht generell
|
||||||
|
für jedes `.add` (z.B. `/ip address` erlaubt legitim mehrere
|
||||||
|
Adressen pro Interface). **Noch nicht erneut live getestet**, siehe
|
||||||
|
Nächste Schritte.
|
||||||
|
|
||||||
**Lehren:** Citadel/NIOSSH-Fehler immer mit `String(describing:)` loggen,
|
**Lehren:** Citadel/NIOSSH-Fehler immer mit `String(describing:)` loggen,
|
||||||
nie `.localizedDescription`. Jede View, die ein ObservableObject aus einem
|
nie `.localizedDescription`. Jede View, die ein ObservableObject aus einem
|
||||||
@@ -741,11 +765,16 @@ beim Ändern die RouterOS-Suffix-Form zurück) — angewendet auf DHCP-Server
|
|||||||
|
|
||||||
## Nächste Schritte
|
## Nächste Schritte
|
||||||
|
|
||||||
1. Den kompletten Wizard einmal neu durchlaufen (WAN/LAN/VLAN/WLAN/
|
1. **In Arbeit, hier weitermachen:** kompletter Wizard-Durchlauf
|
||||||
Firewall) auf dem werksresetteten hEX und dabei das Firewall-Ergebnis
|
(WAN/LAN mit zwei Interfaces ether2+ether3, eins isoliert/Firewall)
|
||||||
mit korrektem WAN-Port per `/ip firewall filter print` /
|
über den Experte-Modus — kombiniert M8-Hardware-Test (Netzwerk-
|
||||||
`/ip firewall nat print` kontrollieren (bisher nur die Interface-
|
Isolation) mit diesem Punkt. Wurde in dieser Session begonnen, brach
|
||||||
Auswahl nach dem Parser-Fix bestätigt, kein erneuter Apply).
|
beim WAN-Schritt mit Bug 21 ab (jetzt gefixt, deployt, aber
|
||||||
|
**ungetestet**). Nach erneutem Durchlauf: Firewall-Ergebnis mit
|
||||||
|
korrektem WAN-Port UND die Isolations-Regeln per
|
||||||
|
`/ip firewall filter print` kontrollieren, plus praktisch testen
|
||||||
|
(iMac ↔ Laptop sollten sich nicht erreichen, Internet für beide
|
||||||
|
schon).
|
||||||
2. WLAN (M5) an einem Gerät mit echtem WLAN-Chip nachholen.
|
2. WLAN (M5) an einem Gerät mit echtem WLAN-Chip nachholen.
|
||||||
3. Rest von M7: Fehlerzustände/Politur, REST-Schreibtest an einem Gerät
|
3. Rest von M7: Fehlerzustände/Politur, REST-Schreibtest an einem Gerät
|
||||||
mit aktivem `www-ssl`.
|
mit aktivem `www-ssl`.
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ final class SetupViewModel: ObservableObject {
|
|||||||
|
|
||||||
for command in plannedCommands {
|
for command in plannedCommands {
|
||||||
applyLog.append(command.summary)
|
applyLog.append(command.summary)
|
||||||
try await connectionService.apply(command)
|
try await applyIdempotently(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
didApplySuccessfully = true
|
didApplySuccessfully = true
|
||||||
@@ -223,4 +223,36 @@ final class SetupViewModel: ObservableObject {
|
|||||||
isApplying = false
|
isApplying = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// RouterOS allows at most one item per interface on some menus (a DHCP client, a PPPoE
|
||||||
|
/// client) — re-running the wizard's WAN step on an interface that already has one makes the
|
||||||
|
/// wizard's own `.add` fail live-confirmed: "failure: dhcp-client on that interface already
|
||||||
|
/// exists". Rather than hard-fail the whole apply here, retry once as a `.set` matched by
|
||||||
|
/// "interface" instead — reconfigures the existing entry in place, which is what re-running
|
||||||
|
/// the wizard on the same interface should mean anyway. Scoped to exactly these two
|
||||||
|
/// known-unique-per-interface menus, not applied generally to every `.add` — other menus
|
||||||
|
/// (e.g. "/ip address") legitimately allow multiple items per interface, where silently
|
||||||
|
/// converting a would-be-duplicate `.add` into a `.set` would be wrong, not helpful.
|
||||||
|
private static let interfaceUniqueMenuPaths: Set<String> = ["/ip dhcp-client", "/interface pppoe-client"]
|
||||||
|
|
||||||
|
private func applyIdempotently(_ command: RouterOSCommand) async throws {
|
||||||
|
do {
|
||||||
|
try await connectionService.apply(command)
|
||||||
|
} catch {
|
||||||
|
guard case .add = command.operation,
|
||||||
|
Self.interfaceUniqueMenuPaths.contains(command.menuPath),
|
||||||
|
let interfaceName = command.arguments["interface"] else {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
let retryCommand = RouterOSCommand.set(
|
||||||
|
menuPath: command.menuPath,
|
||||||
|
restPath: command.restPath,
|
||||||
|
matchField: "interface",
|
||||||
|
matchValue: interfaceName,
|
||||||
|
arguments: command.arguments,
|
||||||
|
summary: command.summary
|
||||||
|
)
|
||||||
|
try await connectionService.apply(retryCommand)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user