TP21: Nautobot-Basisdaten (Ist-Stand) + TP15-Kurskorrektur CRS326 = L3-Router

Nautobot-Ingest (Ist, nicht Ziel):
- Locations: LocationType "Bereich"; Technik UG (Diele, kein Keller) = crs326-core,
  Technik OG = crs326-branch, Wohnzimmer Sideboard = ap1
- Devices: ap2 -> Rolle "Wireless AP" + Offline; beide CRS326 Platform RouterOS
  nachgetragen (fehlte -> haette jeden GC-Job auf ihnen verhindert);
  sw1/sw2/cudy1 als Uebergangs-Devices ohne Platform
- IPAM: VLAN-Group BF, 9 VLANs (VLAN1 deprecated), 8 Prefixes je VLAN-gebunden
- ap1: 26 Interfaces inkl. MACs, ether2 als Trunk, 9 GW-IPs
- WLAN: logischer Controller bf-wlan (kein CAPsMAN), 6 SSIDs mit VLAN-Bindung,
  2 RadioProfiles

Entscheide 2026-07-22:
- crs326-core wird L3-Router; Routing/DNS/DHCP wandern von ap1, APs werden reine APs.
  Ueberschreibt die fruehere "Router bleibt ap1/ap2"-Zeile desselben Tages.
- CAPsMAN wird abgeschafft, beide APs von Nautobot identisch generiert.
- AP-Uplink wandert auf ether1 (PoE-Port). RouterOS nummeriert ab 1, nie ether0.

Befunde:
- Root Cause des ap1-VLAN1-Lecks: cfg-main-2g hat gar keinen datapath-Block ->
  2,4-GHz-main taggt nicht, Bandwechsel = Subnetzsprung. Nicht das frame-types-Thema.
- Beide CRS326 laufen bereits (RouterOS 7.19.5, Werkszustand), beide auf 192.168.88.1
  im selben L2 = IP-Konflikt.
- hAP ax2 PoE ist passiv 18-28V, nicht 802.3af/at; ether1 steht auf poe-out=auto-on.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 21:28:28 +02:00
parent 1578de50c3
commit b0a0b16556
3 changed files with 390 additions and 2 deletions

26
nautobot/README.md Normal file
View File

@@ -0,0 +1,26 @@
# Nautobot-Tooling
## `ingest-baseline.py`
Idempotenter Basisdaten-Ingest (Locations, Rollen, Device-Types, Devices, VLANs/Prefixes,
ap1-Interfaces + IPs, WLAN-Modelle). Bildet den **Ist-Zustand** ab, nicht den Zielzustand.
```bash
export NAUTOBOT_TOKEN=... # aus docs/nas-vlan20/stacks/210-nautobot.yml (gitignored)
python3 nautobot/ingest-baseline.py # Dry-Run
python3 nautobot/ingest-baseline.py --apply # schreiben
```
### API-Fallen (teuer gelernt)
- **`tagged_vlans` liest sich per REST als `null`, obwohl korrekt gespeichert.** Verifikation
nur über GraphQL: `POST /api/graphql/` mit
`{interfaces(device:"ap1"){name mode untagged_vlan{vid} tagged_vlans{vid}}}`.
- Relationen kommen ohne `?depth=1` ohne `display` → ein voll gepflegtes Device sieht leer aus.
- `LocationType.content_types` muss `ipam.vlangroup`/`ipam.vlan`/`ipam.prefix`/`dcim.controller`
enthalten, sonst 400 beim Anlegen.
- `parent_interface` nur für virtuelle Interfaces — WLAN-VAPs können ihren Master nicht als
Parent tragen.
- `WirelessNetwork` hat **kein** VLAN-Feld; die VLAN-Bindung hängt an
`wireless/controller-managed-device-group-wireless-network-assignments` und braucht zwingend
einen `Controller` (bei uns logisch, `controller_device` leer — kein CAPsMAN).
- `RadioProfile.channel_width` will Integer (`[20,40,80]`), nicht `"20mhz"`.
- IP↔Interface läuft über `/ipam/ip-address-to-interface/`.