diff --git a/nautobot/gc-configplan.py b/nautobot/gc-configplan.py index e56d7ca..122ebd6 100644 --- a/nautobot/gc-configplan.py +++ b/nautobot/gc-configplan.py @@ -546,6 +546,56 @@ def job_tp45_agh_dhcp(): return [(["crs326-core"], core_set, "TP45-agh-dhcp")] +def _pool_set(vlan, ranges): + """Zeilen, die `pool-v` auf `ranges` ziehen -- mit gezaehltem Selektor. + + MODIFY, kein add: der Pool existiert, die `add`-Zeile der intended config + wuerfe `already have such name`. Gleiche Form wie `job_tp45_agh_dhcp`. + + 🔴 Der Selektor wird GEZAEHLT, nicht geglaubt (Lehre vom 2026-09-21): ein + `find where`, das 0 trifft, sieht wie „nicht vorhanden" aus und nicht wie + „kaputt" -- ein blankes `set [find where name=…]` liefe ins Leere und der + Job meldete trotzdem Erfolg (dieselbe Klasse wie `dst-address=` + in TP23-agh-firewall.commands.rsc:7, das seit dem 08-25 immer 0 meldete). + + 🔴🔴 **JEDES Statement muss auf EINER Zeile klammer-vollstaendig sein.** + Erste Fassung hatte `:if (...) do={` am Zeilenende -- RouterOS geht dann in + den Fortsetzungs-Modus und zeigt einen ANDEREN Prompt, der netmiko-Treiber + verliert sein Muster und der Deploy stirbt mit + `E1015: Pattern not detected: (redacted)@crs326\\-core\\].*$|#.*$)`. + Der Plan stand danach auf `Failed`, **ohne** etwas geschrieben zu haben. + Deshalb ist jede Zeile hier ein vollstaendiges `… do={ …; … } else={ … }`. + """ + pool = f"pool-v{vlan}" + return "\n".join([ + f':if ([:len [/ip pool find where name="{pool}"]] = 1) do={{ ' + f'/ip pool set [find where name="{pool}"] ranges={ranges}; ' + f':log info ("tp45-pool: {pool} -> " . [/ip pool get [find where name="{pool}"] ranges]) }} ' + f'else={{ :log info ("tp45-pool: ABBRUCH, {pool} nicht eindeutig") }}', + ]) + + +def job_tp45_pool_v20(): + """TP45 (2026-09-21): pool-v20 von .100-.200 auf .200-.249 verengen. + + Damit werden die Schema-Baender .100-.149 (Server-Hosts) und .150-.199 + (App-Services) in VLAN20 echt frei. VLAN20 traegt KEINE DHCP-Reservierung + im alten Fenster (live geprueft: nur `nas-bf .20.10` in .10x) und 0 + dynamische Leases -- die Verengung kostet hier nichts. + + 🔴 Warum ueberhaupt: `nautobot .154-.158`, `gitea .157`, `pve-mcp .173` und + `shelly-mcp .180` tragen ihre IP GERAETELOKAL und stehen in KEINEM + Lease-Eintrag -- der Core kann sie nicht schuetzen und einem DHCP-Client + .154 anbieten. Die Verengung ist hier sofort wirksam. + + ⚠️ VLAN30 gehoert NICHT hierher: dort liegen 35 statische Reservierungen IM + Fenster .200-.249 (26 Shellys .202-.226/.233, SwitchBot .227, Twinkly .228, + Withings .230/.231, lichterketten .236/.237, Nuki .241/.244, CCU .232). + Erst Schicht B zieht die um, DANN pool-v30. + """ + return [(["crs326-core"], _pool_set(20, "10.40.20.200-10.40.20.249"), "TP45-pool-v20")] + + JOBS = { "drift-cleanup": job_drift_cleanup, "mgmt-acl": job_mgmt_acl, @@ -553,6 +603,7 @@ JOBS = { "tp38-oob": job_tp38_oob, "tp45-agh-fw": job_tp45_agh_fw, "tp45-agh-dhcp": job_tp45_agh_dhcp, + "tp45-pool-v20": job_tp45_pool_v20, } diff --git a/nautobot/mikrotik_routeros.j2 b/nautobot/mikrotik_routeros.j2 index b47be08..3c1562a 100644 --- a/nautobot/mikrotik_routeros.j2 +++ b/nautobot/mikrotik_routeros.j2 @@ -36,7 +36,7 @@ {#- VLAN-Tabelle: Site-Konstante. name = RouterOS-comment, lease/pool je VLAN. -#} {%- set vlans = [ {"id": 10, "name": "MAIN", "pool": "10.40.10.100-10.40.10.200", "lease": "1d"}, - {"id": 20, "name": "INFRA", "pool": "10.40.20.100-10.40.20.200", "lease": "1d"}, + {"id": 20, "name": "INFRA", "pool": "10.40.20.200-10.40.20.249", "lease": "1d"}, {"id": 30, "name": "IOT", "pool": "10.40.30.100-10.40.30.250", "lease": "1d"}, {"id": 40, "name": "MEDIA", "pool": "10.40.40.100-10.40.40.200", "lease": "1d"}, {"id": 50, "name": "UNTRUSTED", "pool": "10.40.50.100-10.40.50.200", "lease": "1d"},