Tento dokument popisuje návrhový rámec pro systém, který má pomáhat průběžně skládat pracovní obraz síťové infrastruktury z více neúplných, časově proměnlivých a někdy konfliktních zdrojů dat.
Cílem není pouze vytvořit databázi zařízení ani jednoduchý reporting. Cílem je navrhnout způsob, jak:
- sbírat pozorování z externích zdrojů,
- udržet stabilní identitu objektů,
- odvozovat aktuální stav,
- zachovat auditovatelnost původu dat,
- zobrazovat člověku použitelné pracovní pohledy,
- průběžně upravovat model podle nových zjištění.
Pracovní formulace problému:
Jak nad proměnlivou infrastrukturou průběžně sbírat pozorování, udržet identitu objektů, odvozovat aktuální stav a zobrazovat člověku pracovní obraz reality, aniž by se surová data, interpretace a reporty slily do jednoho chaosu.
Tento dokument popisuje co systém eviduje a jaká pravidla musí každá implementace dodržet. Nepopisuje jak se to konkrétně programuje. Tedy:
Co je v dokumentu:
- jaké tabulky existují a jaké mají sloupce
- jaké jsou vztahy mezi tabulkami
- co skripty smí a nesmí dělat z pohledu dat
- kontrakt mezi skripty a databází
Co v dokumentu NENÍ:
- konkrétní SNMP MIBy, ifIndex stabilita, vendor specifika
- jak normalizovat názvy portů
- v jakém jazyce skripty psát
- jak agent řeší autentizaci k zařízení
Implementační detaily se rozhodují v okamžiku implementace – buď ručně, nebo s pomocí agenta. Dokument se jich nemá držet, jinak by zastaral u první vendor-specific zvláštnosti.
Pokud implementuješ skripty podle tohoto dokumentu, čti v tomto pořadí:
1. kapitola 4 architektura vrstev (co je core, obs, plan, ...)
2. kapitola 5.1 role skriptů obecně
3. kapitola 5.1.4 pravidla zakládání identit (co skript smí auto-zakládat)
4. kapitola 7 skripty první fáze - hranice, kontrakt, konvence
5. kapitola 6.7 SQL schéma databáze
Zbytek dokumentu je kontext a vysvětlení, proč jsou pravidla taková, jaká jsou. Není povinný, ale pomáhá pochopit hranice.
V dokumentu jsou dva typy pravidel:
> Datový kontrakt (závazné). Porušení = porušení modelu.
> Vymáhá se reviewem schématu a dat.
> Implementační konvence. Porušení = technický dluh.
> Vymáhá se reviewem kódu.
Sekce, které spadají do prvního typu, jsou v textu označeny „Datový kontrakt (závazné)" v blockquote na začátku. Pokud jsi agent nebo implementátor, dodrž je doslovně.
Systém nemá sloužit pouze k evidenci aktuální infrastruktury. Má podporovat několik souvisejících, ale odlišných cílů.
Prvním účelem je průběžně skládat pracovní obraz existující síťové infrastruktury z více zdrojů dat.
Tato část odpovídá na otázky:
Co v síti reálně existuje?
Kde se to nachází?
Jak to spolu souvisí?
Co je jisté?
Co je pouze pozorování?
Co je konflikt?
Co je zastaralé?
Co je potřeba ručně ověřit?
Druhým účelem je vytvořit obraz cílového stavu nové infrastruktury.
Cílový stav nevzniká nezávisle „od stolu“. Vychází z pozorování a interpretace stávajícího stavu, ale zároveň umožňuje evidovat další parametry, které jsou specifické pro plánovaný cílový stav.
Jinými slovy:
observed/current reality
→ interpreted current state
→ target design
→ migration mapping
Nejde pouze o evidenci toho, co existuje dnes, ale také o návrh toho, co má existovat po upgradu nebo výměně síťových prvků.
Tato část odpovídá na otázky:
Jaká zařízení budou v nové infrastruktuře?
Jaké porty/interfacy budou mít?
Jaké VLANy, subnety a segmenty budou použity?
Jaké role budou mít nové porty?
Jak se změní topologie?
Jaké části staré infrastruktury budou nahrazeny?
Třetím účelem je promapovat starou infrastrukturu na novou pro účely migrace.
Primární migrační jednotkou je port/interface, ne celé zařízení. Reálná migrační otázka typicky zní:
Který starý port odpovídá kterému novému portu?
Mapování zařízení jako celek může být ve většině případů odvozené ze souboru portových mapování. Nemusí proto být v minimálním modelu samostatnou primární tabulkou.
Tato část odpovídá na otázky:
Který starý port odpovídá kterému novému portu?
Které VLANy/segmenty se přenášejí beze změny?
Které VLANy/segmenty se mění?
Které vazby jsou ověřené a které pouze předpokládané?
Co ještě není namapované?
Co je konfliktní nebo nejasné?
Jaký souhrnný vztah starých a nových zařízení plyne z mapování portů?
Tento účel je důležitý zejména pro výměnu síťových prvků, kdy je potřeba pochopit současný stav, navrhnout cílový stav a řídit přechod mezi nimi.
Čtvrtým účelem je poskytovat pracovní pohledy pro samotnou migraci.
Příklady:
starý port → nový port
starý port → zjištěné MAC/IP/segmenty
nový port → plánovaná konfigurace
rozdíl mezi zjištěnou realitou a plánem
nenamapované porty
porty s konfliktními daty
porty připravené k migraci
souhrn starý switch → nový switch odvozený z portových mapování
Systém tedy musí umět pracovat nejen s tím, co bylo pozorováno, ale i s tím, co je plánováno.
Důležité rozlišení:
Současný stav
je rekonstruovaný z pozorování a ruční evidence.
Cílový stav
je plánovaný návrh, který může vycházet ze současného stavu,
ale může obsahovat nové vlastnosti, nové role, nové konfigurace
a nové vazby, které ve staré infrastruktuře neexistují.
Migrační mapování
propojuje současný stav s cílovým stavem a říká,
co se přenáší, co se mění a co je potřeba ověřit.
Tato část popisuje, jaké problémy systém řeší a jak je strukturován konceptuálně, nezávisle na konkrétní implementaci.
Síťová infrastruktura není statická evidence. Je to proměnlivý systém, u kterého se skutečný stav skládá z více zdrojů:
- MAC tabulky ze switchů,
- ARP tabulky z firewallů/routerů,
- konfigurace zařízení,
- ručně udržovaná evidence,
- subnety a segmenty,
- VLANy,
- historická pozorování,
- případně data z NetBoxu nebo jiných systémů.
Každý zdroj říká pouze část pravdy. Některé informace mohou být neúplné, zastaralé nebo konfliktní.
Příklad:
SNMP MAC tabulka říká:
MAC X byla v čase T viděna na portu P.
ARP tabulka říká:
IP Y byla v čase T spojena s MAC X.
Evidence subnetů říká:
IP Y patří do subnetu S.
Evidence segmentů říká:
subnet S patří do segmentu Z.
Konfigurace portu říká:
port P je access/trunk/uplink/neznámý.
Otázka „jaké segmenty jsou za portem“ proto není jen prostý JOIN. Je to interpretace více vrstev reality.
Systém musí důsledně rozlišovat minimálně tři úrovně:
Pozorování
Co bylo někde viděno nebo zjištěno.
Odvozený stav
Co z pozorování považujeme za aktuálně platný nebo pravděpodobný stav.
Lidský pohled
Jak chceme výsledek zobrazit člověku pro práci, kontrolu nebo rozhodování.
Toto rozlišení je klíčové. Pokud se pozorování, interpretace a reportovací pohledy smíchají do jedné vrstvy, systém se rychle stane nepřehledným a nedůvěryhodným.
Při skládání obrazu síťové reality se překrývá více dimenzí.
Je potřeba určit, co je stejný objekt:
- zařízení,
- interface,
- MAC adresa,
- IP adresa,
- subnet,
- VLAN,
- segment.
Příklad:
aa-bb-cc-dd-ee-ff
AA:BB:CC:DD:EE:FF
aabb.ccdd.eeff
mohou reprezentovat stejnou MAC adresu, ale musí být normalizovány.
Pozorování má vždy časový kontext.
Příklad:
MAC X byla viděna na portu P před 5 minutami.
MAC X byla viděna na portu Q před 3 dny.
Systém musí rozlišovat:
- historické pozorování,
- aktuálně relevantní pozorování,
- zastaralé pozorování,
- konflikt mezi pozorováními.
Každá informace má původ.
Příklady zdrojů:
- SNMP,
- ARP,
- konfigurace zařízení,
- ruční evidence,
- NetBox,
- importní skript,
- jednorázový CSV import.
Zdroj je důležitý pro důvěryhodnost i auditovatelnost.
Různé zdroje mohou mít různou váhu.
Příklad:
Ruční potvrzená evidence může mít vyšší váhu než jednorázové pozorování.
Aktuální SNMP výstup může mít vyšší váhu než starý ARP záznam.
MAC viděná na uplinku nemusí znamenat koncové zařízení za portem.
Důvěryhodnost by neměla být schovaná v neviditelné logice skriptu bez možnosti zpětného vysvětlení.
Informace je potřeba zasadit do síťového kontextu:
- zařízení,
- port,
- VLAN,
- subnet,
- segment,
- uplink/access/trunk role portu,
- vztah mezi porty a zařízeními.
Vztahy nejsou vždy jednoduché 1:1.
Příklady:
Jeden port může vidět více MAC adres.
Jedna MAC může být v historii viděna na více portech.
Jedna MAC může mít více IP adres.
Jedna IP může být časově spojena s různými MAC adresami.
Jeden segment může být dosažitelný přes více portů.
Právě zde vzniká riziko duplicit, násobení řádků a chybných agregací.
Technická vazba neznamená automaticky správný význam.
Příklad:
Port vidí MAC adresy z více segmentů.
To může znamenat:
- port je trunk,
- port je uplink,
- za portem je další switch,
- je tam virtualizační host,
- je tam chyba v datech,
- jde o historický/stale stav.
Systém musí umožnit zobrazit nejen výsledek, ale i signály nejistoty.
Systém nemá být jen databází ani jen reportingem.
Má být navržen jako pipeline:
Evidence objektů
→ Pozorování
→ Interpretace
→ Odvozený stav
→ Pracovní pohledy
→ Reportovací pohledy
Nejdůležitější myšlenka:
Síťová realita je rekonstruovaná z pozorování. Proto musí systém odlišovat, co bylo viděno, co z toho odvozujeme a jak to zobrazujeme člověku.
Tato část popisuje jednotlivé vrstvy navrženého modelu a jejich odpovědnosti.
Pracovní návrh vrstev:
core.*
stabilní identity objektů současné/reálné infrastruktury
obs.*
surová pozorování a importní dávky
work.*
pracovní interpretační views nad aktuální realitou
derived.*
fyzicky uložený odvozený stav, pokud už nestačí jednoduchý SQL view
plan.*
plánovaný cílový stav nové infrastruktury
migration.*
mapování mezi současným a cílovým stavem
report.*
stabilnější lidské pohledy pro reporting / UI
Vrstva core drží stabilní entity a jejich základní integritu.
Příklady tabulek:
core.devices
core.interfaces
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
core.vlans
Tato vrstva odpovídá na otázku:
Jaké objekty v našem modelu existují a jaké mají stabilní identity?
Typické vlastnosti:
- primární klíče,
- foreign keys,
- unique constraints,
- normalizované hodnoty,
- základní popisné atributy,
- ručně ověřené nebo dlouhodobě platné údaje.
Vrstva obs drží pozorování ze skriptů a externích zdrojů.
Příklady tabulek:
obs.import_batches
obs.mac_port_observations
obs.arp_observations
obs.interface_status_observations
obs.config_observations
Tato vrstva odpovídá na otázku:
Co jsme kdy, kde a z jakého zdroje viděli?
Důležité pravidlo:
Importní skript by měl primárně ukládat pozorování, ne neviditelně rozhodovat o finální pravdě.
Příklad interpretace:
Špatně:
MAC X je za portem P.
Lépe:
V čase T zdroj S tvrdil, že MAC X byla viděna na portu P.
Každé pozorování by mělo mít minimálně:
observed_at,source,batch_id,- vazbu na normalizované entity, pokud existují,
- případně raw hodnoty a raw payload.
Vrstva work obsahuje pracovní interpretační pohledy.
Tato vrstva odpovídá na otázku:
Co z dostupných pozorování pravděpodobně plyne podle aktuálně definovaných pravidel?
Příklady:
work.current_mac_locations
work.current_ip_mac_bindings
work.current_port_segments
work.conflicting_mac_locations
work.data_quality_issues
work.stale_observations
Tyto views nejsou jen reporty. Jsou to pracovní čočky, které pomáhají skládat obraz reality.
Příklad pravidla:
Za aktuální lokaci MAC považuj poslední pozorování za posledních 24 hodin,
pokud nejde o port označený jako uplink/trunk.
Pokud je pravidlo jednoduché, může být vyjádřeno SQL view.
Pokud začne být pravidlo složité, může být vhodnější přesun do skriptu nebo do derived vrstvy.
Vrstva derived slouží pro fyzicky uložený odvozený stav.
Použije se tehdy, když:
- interpretační logika je složitá,
- výpočet je drahý,
- je potřeba uchovat výsledek rozhodnutí,
- je potřeba auditovat, proč byl stav odvozen právě takto,
- je potřeba kombinovat více pravidel, scoring nebo ruční override.
Příklad tabulky:
derived.current_mac_locations
Možná pole:
mac_id
interface_id
device_id
vlan_id
observed_at
source
confidence
decision_reason
updated_at
Důležité pravidlo:
Pokud systém něco interpretuje jako aktuální stav, měl by být dohledatelný důvod tohoto rozhodnutí.
Vrstva plan obsahuje cílový návrh nové infrastruktury.
Tato vrstva odpovídá na otázku:
Co má existovat po upgradu nebo výměně síťových prvků?
Příklady tabulek:
plan.target_devices
plan.target_interfaces
plan.target_vlans
plan.target_interface_configs
plan.target_port_roles
Cílový stav může vycházet ze současné infrastruktury, ale není jejím prostým kopírováním.
Může obsahovat cílově specifické parametry, například:
nový název zařízení
nový model zařízení
nové číslování portů
cílová role portu
cílová VLAN konfigurace
cílový popis portu
plánovaný access/trunk režim
poznámka k fyzickému přepojení
migrační priorita
stav připravenosti
Důležité pravidlo:
Cílový stav musí být možné odvodit nebo předvyplnit ze současného stavu, ale následně ručně upravit a doplnit o parametry, které ve staré infrastruktuře neexistují.
Vrstva migration propojuje současnou a cílovou infrastrukturu.
Tato vrstva odpovídá na otázku:
Jak se starý svět mapuje na nový svět?
Příklady tabulek:
migration.interface_mappings
migration.vlan_mappings
migration.segment_mappings
migration.migration_notes
Primární tabulkou pro první implementační model je migration.interface_mappings.
Explicitní migration.device_mappings není součástí minimálního modelu. Vztah starého a nového zařízení bude nejprve odvozován jako souhrnný pohled nad portovým mapováním.
Příklad mapování:
starý interface → nový target interface
starý VLAN/segment → cílová VLAN/segment
Mapování by mělo umožnit evidovat:
stav mapování: proposed / verified / migrated / blocked
zdroj mapování: ručně / import / odvozeno z názvu / odvozeno z port pořadí
jistotu mapování
poznámku
blokující problém
Důležité pravidlo:
Mapování není jen technická vazba. Je to pracovní rozhodnutí, které může být navržené, ověřené, změněné nebo odmítnuté.
Z toho vyplývá, že mapování musí umět nést historii rozhodnutí, ne jen aktuální stav. Pokud někdo navrhne mapování, později ho zamítne a navrhne jiné, musí být dohledatelné, proč se to stalo.
První verze proto v migration.interface_mappings zavádí příznak is_current a partial unique indexy:
- v jednu chvíli je za daný source port aktivní nejvýše jedno mapování,
- v jednu chvíli je za daný target port aktivní nejvýše jedno mapování,
- starší (neaktuální) mapování zůstávají uložená pro audit.
Tento přístup řeší 1:1 případy, návrhové iterace a rejecty. M:N případy (LAG, split, merge) zůstávají jako otevřená otázka a vyžadují diskuzi (viz sekce 9).
Mapování zařízení není v první verzi považováno za primární vstupní entitu.
Důvod:
Pokud máme dostatečně přesné mapování portů,
souhrnný vztah staré zařízení → nové zařízení
lze odvodit z těchto portových mapování.
Příklad:
old huawei-sw01 Gi0/0/1 → new cisco-sw01 Gi1/0/1
old huawei-sw01 Gi0/0/2 → new cisco-sw01 Gi1/0/2
old huawei-sw01 Gi0/0/3 → new cisco-sw01 Gi1/0/3
Z toho lze reportovat:
huawei-sw01 → cisco-sw01
mapped_ports: 3
mapping_type: full/partial podle rozsahu
Explicitní tabulka migration.device_mappings se doplní až tehdy, pokud bude potřeba evidovat zařízení jako samostatný migrační objekt nezávisle na portech.
Typické důvody pro pozdější doplnění:
- jeden starý switch se rozpadá do více nových switchů,
- více starých switchů se slučuje do jednoho nového,
- je potřeba řídit migrační fázi na úrovni zařízení,
- je potřeba evidovat fyzickou výměnu kus za kus,
- cílové zařízení se plánuje dříve než detailní port mapping.
Pro první implementaci bude zařízení mapováno přes reportovací pohled:
report.device_mapping_summary
Vrstva report obsahuje stabilnější pohledy pro člověka nebo nástroje typu Metabase.
Tato vrstva odpovídá na otázku:
Jak chceme výsledek přehledně zobrazit člověku?
Příklady:
report.segments_behind_port
report.device_mapping_summary
report.device_overview
report.interface_overview
report.mac_inventory
report.ip_inventory
Tato vrstva už může obsahovat lidsky čitelné agregace:
port → seznam MAC adres
port → seznam IP adres
port → seznam segmentů
port → počet segmentů
port → příznaky konfliktů
Příklad výstupu:
Device: sw01
Interface: Gi1/0/5
MAC count: 4
Segments: LAN, Printers
Flags: mixed_segments, stale_arp
Tato část popisuje, jak má systém pracovat v praxi: jak se chovají importní skripty, jak se interpretují data a jaké zásady drží návrh konzistentní.
Externí skripty slouží hlavně pro sběr dat a případně pro složitější interpretaci.
Skript by měl:
- vytvořit importní dávku,
- stáhnout data ze zdroje,
- normalizovat základní formát,
- uložit raw hodnoty,
- propojit data na core entity, pokud je to možné,
- uložit pozorování do
obs.*, - aktualizovat základní metadata typu
first_seen/last_seen, - ukončit importní dávku.
Skript by neměl neviditelně:
- přepisovat finální pravdu,
- mazat starší kontext,
- schovávat konflikty,
- rozhodovat bez auditní stopy,
- míchat pozorování a interpretaci do jedné tabulky.
Skript dává smysl pro interpretaci, pokud pravidla zahrnují:
- scoring,
- více kroků,
- ruční override,
- porovnávání více zdrojů,
- detekci konfliktů,
- ignorování portů podle role,
- historické okno,
- složitější heuristiky.
Výsledek takové interpretace by měl být uložen do derived.*, ideálně s poli jako:
confidence
decision_reason
source_basis
updated_at
Datový kontrakt (závazné). Každý skript, který importuje data do
obs.*nebocore.*, musí dodržet pravidla v této sekci. Porušení vede k nekonzistentním identitám napříč zdroji.
Skripty při importu narážejí na entity, které ještě v core.* neexistují. Otázka „co se s nimi má stát" nesmí být schovaná v implementaci jednotlivých skriptů – jinak se rychle objeví nekonzistentní stav: jeden skript MAC založí, jiný ne, třetí v jiném formátu.
Pracovní pravidla pro první verzi:
MAC adresy
Auto-zakládat v core.mac_addresses.
Riziko nízké, MAC je technicky jednoznačná identita.
Skript nastaví first_seen a last_seen.
IP adresy
Auto-zakládat v core.ip_addresses.
Pokud existuje matching subnet, propojit přes subnet_id.
Pokud ne, založit s subnet_id = NULL a označit pro pozdější revizi.
VLANy
Auto-zakládat v core.vlans, pokud jsou viděné v pozorování.
Source nastavit na 'discovered', label může zůstat prázdný.
Operátor doplní label a purpose ručně později.
Interfaces na známém zařízení
Auto-zakládat v core.interfaces.
Switche běžně získávají/ztrácí porty (subinterfaces, LAGy, VLAN interfaces);
blokovat tohle by znamenalo bránit normálnímu provozu.
Source nastavit na 'discovered'.
Zařízení (devices)
NEAUTO-zakládat.
Skript při neznámém zařízení skončí s jasnou chybou
nebo uloží pozorování bez device_id (raw_device se uloží vždy).
Důvod: zařízení je primární migrační kotva,
jeho založení patří k záměrnému operátorskému rozhodnutí.
Důležité pravidlo:
Auto-zakládat lze entity, které jsou technicky jednoznačné a nesou nízké riziko nesprávné identifikace. Operátorské rozhodnutí (typicky zařízení) musí zůstat explicitní.
Skript musí v každém případě:
- zaznamenat raw_* hodnoty pro pozdější ruční dohledání,
- propojit s batch_id pro auditovatelnost,
- ne maskovat selhání tichým ignorováním.
Otázka:
Jaké segmenty jsou za tímto portem?
Na první pohled jde o jednoduchý report. Ve skutečnosti je to řetězec interpretací.
Potřebné kroky:
1. Najít MAC adresy nedávno viděné za portem.
2. Rozhodnout, která MAC pozorování jsou aktuálně relevantní.
3. Najít IP adresy spojené s těmito MAC adresami.
4. Rozhodnout, která ARP pozorování jsou aktuálně relevantní.
5. Najít subnety těchto IP adres.
6. Najít segmenty těchto subnetů.
7. Zohlednit roli portu.
8. Označit konflikty nebo nejistoty.
9. Zobrazit člověku souhrnný výsledek.
Technická cesta může vypadat takto:
interface
→ mac_port_observations
→ mac_addresses
→ arp_observations
→ ip_addresses
→ subnets
→ segments
Ale správný pohled musí navíc řešit:
- časovou platnost,
- konflikty,
- roli portu,
- duplicitní hodnoty,
- agregaci do lidsky čitelného seznamu,
- signály nejistoty.
Pracovní zásady:
1. Surová pozorování nemažeme bez důvodu.
2. Každý import má batch_id.
3. Každé pozorování má observed_at a source.
4. Core entity mají stabilní ID.
5. Pozorování a interpretace jsou oddělené vrstvy.
6. Aktuální stav je odvozený, ne automaticky surový fakt.
7. Každé složitější rozhodnutí musí být vysvětlitelné.
8. Reportovací pohledy se staví nad interpretační vrstvou, ne přímo nad raw chaosem.
9. Opakovaná otázka se může stát pracovním view.
10. Složitý view je lepší rozdělit na menší vrstvy.
Tato část je konkrétním návrhem první implementační verze: postup, datový model, SQL schéma a otevřené body k doplnění.
Nejrychlejší cesta k cíli nebude začít psaním SQL ani kreslením kompletního modelu. Vhodnější je postupovat po krátkých rozhodovacích blocích, kde se vždy zodpoví jedna oblast a výsledek se rovnou promítne do návrhu.
Navržený pracovní postup:
1. Definovat první reálný use-case.
2. Vyjmenovat zdroje dat pro tento use-case.
3. Rozlišit, co je stabilní entita a co je pozorování.
4. Navrhnout minimální core tabulky.
5. Navrhnout minimální observation tabulky.
6. Definovat pravidla aktuálnosti.
7. Definovat první pracovní interpretační views.
8. Definovat první reportovací pohledy.
9. Teprve potom vytvořit SQL CREATE skripty.
10. Nakonec navrhnout importní skripty a jejich odpovědnosti.
Důležité pravidlo:
Nejdřív modelovat jeden konkrétní pracovní problém. Teprve potom model zobecňovat.
Jako první kandidát use-case se nabízí:
Pro každý switchport zobrazit:
- zařízení,
- interface,
- MAC adresy viděné za portem,
- IP adresy spojené s těmito MAC adresami,
- subnety,
- segmenty,
- informaci o aktuálnosti,
- případné konflikty nebo nejistoty.
Tento use-case je vhodný, protože pokrývá většinu klíčových vrstev systému:
core.devices
core.interfaces
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
obs.mac_port_observations
obs.arp_observations
work.current_mac_locations
work.current_ip_mac_bindings
report.segments_behind_port
První konkrétní implementační use-case bude příprava výměny síťových prvků.
Cílem je pro každý port staré infrastruktury zjistit nebo evidovat:
- na kterém zařízení a portu se nachází,
- jaké MAC adresy byly za portem pozorovány,
- jaké IP adresy byly s těmito MAC adresami spojeny,
- do jakých subnetů a segmentů tyto IP adresy patří,
- zda jsou data aktuální nebo zastaralá,
- zda existují konflikty nebo nejistoty,
- na jaký cílový port nové infrastruktury se má starý port mapovat,
- jaká má být cílová konfigurace nového portu,
- zda je migrace daného portu připravena.
Pro tento use-case budou potřeba tyto oblasti:
current/core
stabilní entity současné infrastruktury
observations
zjištění ze SNMP, ARP, konfigurací a dalších zdrojů
interpreted/current state
pracovní odvození aktuálního stavu
target/plan
cílová infrastruktura a plánované parametry
migration mapping
mapování starých prvků a portů na nové
report/work views
lidsky použitelné pohledy pro kontrolu a migraci
Pracovní minimální sada tabulek:
core.devices
core.interfaces
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
core.vlans
obs.import_batches
obs.mac_port_observations
obs.arp_observations
obs.interface_config_observations
obs.interface_status_observations
plan.target_devices
plan.target_interfaces
plan.target_interface_configs
migration.interface_mappings
migration.migration_notes
První pracovní interpretační views:
work.current_mac_locations
work.current_ip_mac_bindings
work.current_port_segments
work.conflicting_mac_locations
work.stale_observations
work.data_quality_issues
První reportovací/migrační views:
report.segments_behind_port
report.port_migration_overview
report.device_mapping_summary
report.unmapped_current_ports
report.target_ports_without_mapping
report.port_readiness_overview
Před vytvořením SQL CREATE skriptů je potřeba rozhodnout:
1. Jak budeme rozlišovat stará/current zařízení od cílových/target zařízení.
2. Zda cílová zařízení budou samostatně v plan.*, nebo společně v core.* s lifecycle stavem.
3. Jaké stavy bude mít mapování portů.
4. Jak bude odvozován souhrnný device mapping z portových mapování.
5. Jaké základní role portů budeme evidovat.
6. Jaké časové okno znamená aktuální MAC/ARP pozorování.
7. Jak budeme označovat konfliktní nebo neověřená data.
Pracovní návrh výchozích odpovědí:
1. Současnou realitu držet v core.* a obs.*.
2. Cílový plán držet odděleně v plan.*.
3. Primární migrační mapování držet na úrovni portů v migration.interface_mappings.
4. Device mapping zatím neukládat jako primární tabulku, ale odvozovat přes report.device_mapping_summary.
5. Aktuální stav odvozovat nejdříve přes work.* views.
6. Složitější rozhodnutí později přes derived.* tabulky.
Před návrhem konkrétních tabulek je potřeba ujasnit, co je základní evidenční vrstva a co už je pouze pozorování nebo plán.
Základní evidenční vrstva musí obsahovat minimálně objekty, které jsou stabilními kotvami pro pozorování i migraci.
Pro první implementační model jsou primární kotvy:
current device
current interface
Důvod:
Migrace se reálně plánuje a kontroluje na úrovni portů.
Pozorování MAC/ARP/config/status musí být vztažitelné ke konkrétnímu zařízení a portu.
Cílový plán musí být mapovatelný na konkrétní nový port.
Základní evidenční vrstva tedy není pouze seznam switchů. Musí obsahovat i porty/interfacy.
Pracovní minimum:
core.devices
core.interfaces
Další entity, například MAC, IP, subnet, segment a VLAN, jsou také důležité, ale pro migrační mapování mají jinou roli:
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
core.vlans
Tyto entity pomáhají vysvětlit, co je za portem, ale nejsou primární migrační jednotkou.
Současný stav a cílový stav je vhodné tabulkově oddělit.
Pracovní rozhodnutí:
core.*
aktuální / existující / zjištěná infrastruktura
plan.*
plánovaný cílový stav nové infrastruktury
Důvod oddělení:
Současný stav je rekonstruovaný z reality a pozorování.
Cílový stav je návrh, který může obsahovat vlastnosti, které dnes ještě neexistují.
Cílový stav může vzniknout předvyplněním ze současného stavu, ale musí být ručně upravitelný.
Migrace musí umět porovnat „co je“ proti „co má být“.
Pokud by současná a cílová zařízení byla ve stejné tabulce, bylo by nutné zavést silnou lifecycle logiku a hlídat, kdy je záznam realita a kdy plán. To by v první verzi model zbytečně komplikovalo.
Observed svět patří do obs.*.
Observed data nejsou primárně evidence cílového ani aktuálního stavu. Jsou to časově označená tvrzení zdrojů.
Příklad:
MAC tabulka neříká definitivně „toto zařízení je za portem“.
Říká: „v čase T byla MAC M viděna na portu P“.
ARP tabulka neříká definitivně „tato IP patří tomuto zařízení“.
Říká: „v čase T byla IP I spojena s MAC M“.
Proto:
obs.mac_port_observations
obs.arp_observations
obs.interface_status_observations
obs.interface_config_observations
Observed vrstva má být historická, auditovatelná a nesmí se tvářit jako definitivní pravda.
Pro základní technickou rekonstrukci vazby port → MAC → IP → subnet → segment může stačit:
MAC table
ARP table
subnets
segments
Pro migrační účely to ale nestačí vždy.
Důvod:
Při migraci často nechceme vědět jen „jaké MAC/IP jsou za portem“.
Chceme vědět i „co to je zač“ a zda je to migračně důležité.
Příklady:
Za portem je tiskárna.
Za portem je kamera.
Za portem je AP.
Za portem je server.
Za portem je virtualizační host.
Za portem je neznámé zařízení, které se musí ověřit.
Za portem je kritické zařízení, které se musí hlídat při migraci.
Proto je nutné přidat evidenční vrstvu pro koncová nebo sledovaná zařízení.
Pracovní název:
core.assets
Tato vrstva není povinná pro každý endpoint v síti – evidovat každou pracovní stanici by bylo nereálné. Ale je povinná pro každé zařízení, u kterého má migrace dopad: kritické servery, AP, kamery, tiskárny, virtualizační hosty, neznámé entity k ověření. Kritičnost zařízení za portem často rozhoduje, zda migrační okno použít v noci nebo ve špičce, takže core.assets přestává být vedlejší informací a stává se klíčovým vstupem pro plánování.
Příklad:
core.assets
- id
- label
- asset_type
- criticality
- owner
- migration_watch
- last_verified_at
- verified_by
- note
Pole last_verified_at a verified_by jsou důležitá proto, že evidence významných zařízení rychle stárne. Při migraci je rozdíl mezi „evidence říká, že tohle je server zákazníka A, ale nikdo to neviděl dva roky" a „ověřeno před měsícem".
A vazby:
asset ↔ MAC address
asset ↔ IP address
asset ↔ expected/current interface
Důležité pravidlo:
MAC/IP pozorování ukazuje technickou stopu. Asset evidence říká, co tato stopa znamená pro člověka a migraci.
Pro první implementaci se nabízí tyto vrstvy:
core.devices
současné síťové prvky
core.interfaces
porty/interfacy současných síťových prvků
core.mac_addresses
normalizované MAC adresy
core.ip_addresses
normalizované IP adresy
core.subnets
subnety
core.segments
logické segmenty
core.vlans
VLAN evidence
core.assets
evidence významných koncových nebo sledovaných zařízení (servery, AP, kamery, kritické endpointy)
obs.*
pozorování ze sítě
work.*
interpretace aktuálního stavu
plan.*
cílový návrh nové infrastruktury
migration.*
mapování starý port → nový port
report.*
pracovní a migrační pohledy
Tento diagram ukazuje systém po vrstvách. Nejde ještě o přesný ER model tabulek, ale o logické rozdělení odpovědností.
flowchart TB
subgraph CURRENT[Současná evidenční vrstva - core]
D[core.devices<br/>aktuální síťové prvky]
I[core.interfaces<br/>aktuální porty/interfacy]
M[core.mac_addresses]
IP[core.ip_addresses]
S[core.subnets]
SEG[core.segments]
V[core.vlans]
A[core.assets<br/>významná sledovaná zařízení<br/>servery, AP, kamery, kritické endpointy]
end
subgraph OBS[Observed vrstva - obs]
B[obs.import_batches]
MPO[obs.mac_port_observations<br/>MAC viděná na portu v čase]
ARP[obs.arp_observations<br/>IP-MAC vazba v čase]
CFG[obs.interface_config_observations]
ST[obs.interface_status_observations]
end
subgraph WORK[Interpretační vrstva - work/derived]
CML[work.current_mac_locations]
CIM[work.current_ip_mac_bindings]
CPS[work.current_port_segments]
DQ[work.data_quality_issues]
end
subgraph PLAN[Cílový stav - plan]
TD[plan.target_devices]
TI[plan.target_interfaces]
TC[plan.target_interface_configs]
end
subgraph MIG[Migrační vrstva - migration]
IM[migration.interface_mappings<br/>starý port → nový port]
MN[migration.migration_notes]
end
subgraph REPORT[Reportovací/pracovní pohledy - report]
R1[report.segments_behind_port]
R2[report.port_migration_overview]
R3[report.device_mapping_summary]
R4[report.port_readiness_overview]
end
D --> I
I --> MPO
M --> MPO
M --> ARP
IP --> ARP
IP --> S
S --> SEG
V --> I
A -. může být spojeno s .-> M
A -. může být spojeno s .-> IP
B --> MPO
B --> ARP
B --> CFG
B --> ST
MPO --> CML
ARP --> CIM
CML --> CPS
CIM --> CPS
CPS --> R1
DQ --> R4
TD --> TI
TI --> TC
I --> IM
TI --> IM
IM --> R2
IM --> R3
IM --> R4
R1 --> R2
Tento diagram ukazuje konkrétnější vztahy mezi hlavními tabulkami první implementační verze. Je to pracovní návrh, ne finální databázové schéma.
erDiagram
core_devices ||--o{ core_interfaces : has
core_vlans ||--o{ core_interfaces : native_or_default_vlan
core_segments ||--o{ core_subnets : contains
core_vlans ||--o{ core_subnets : may_map_to
core_subnets ||--o{ core_ip_addresses : contains
core_mac_addresses ||--o{ obs_mac_port_observations : observed_as
core_interfaces ||--o{ obs_mac_port_observations : observed_on
core_devices ||--o{ obs_mac_port_observations : observed_on_device
core_vlans ||--o{ obs_mac_port_observations : observed_in_vlan
obs_import_batches ||--o{ obs_mac_port_observations : contains
core_ip_addresses ||--o{ obs_arp_observations : observed_as
core_mac_addresses ||--o{ obs_arp_observations : paired_with
core_devices ||--o{ obs_arp_observations : observed_on_device
core_interfaces ||--o{ obs_arp_observations : optionally_observed_on
obs_import_batches ||--o{ obs_arp_observations : contains
core_assets ||--o{ core_asset_mac_addresses : identified_by
core_mac_addresses ||--o{ core_asset_mac_addresses : belongs_to_asset
core_assets ||--o{ core_asset_ip_addresses : identified_by
core_ip_addresses ||--o{ core_asset_ip_addresses : belongs_to_asset
plan_target_devices ||--o{ plan_target_interfaces : has
plan_target_interfaces ||--o{ plan_target_interface_configs : configured_by
plan_target_vlans ||--o{ plan_target_interface_configs : access_or_native_target_vlan
core_segments ||--o{ plan_target_vlans : target_segment_for
core_interfaces ||--o{ migration_interface_mappings : source_current_interface
plan_target_interfaces ||--o{ migration_interface_mappings : target_planned_interface
migration_interface_mappings ||--o{ migration_migration_notes : has
core_devices {
bigint id PK
text label
text hostname
inet mgmt_ip
text vendor
text model
}
core_interfaces {
bigint id PK
bigint device_id FK
text name
text role
bigint native_vlan_id FK
}
core_mac_addresses {
bigint id PK
macaddr mac
timestamptz first_seen
timestamptz last_seen
}
core_ip_addresses {
bigint id PK
inet address
bigint subnet_id FK
timestamptz first_seen
timestamptz last_seen
}
core_subnets {
bigint id PK
cidr prefix
bigint segment_id FK
bigint vlan_id FK
}
core_segments {
bigint id PK
text label
}
core_vlans {
bigint id PK
integer vlan_id
text label
}
core_assets {
bigint id PK
text label
text asset_type
text criticality
boolean migration_watch
}
core_asset_mac_addresses {
bigint asset_id FK
bigint mac_id FK
}
core_asset_ip_addresses {
bigint asset_id FK
bigint ip_address_id FK
}
obs_import_batches {
bigint id PK
text source
text source_type
timestamptz started_at
timestamptz finished_at
text status
}
obs_mac_port_observations {
bigint id PK
bigint batch_id FK
timestamptz observed_at
bigint device_id FK
bigint interface_id FK
bigint mac_id FK
bigint vlan_id FK
}
obs_arp_observations {
bigint id PK
bigint batch_id FK
timestamptz observed_at
bigint device_id FK
bigint interface_id FK
bigint ip_address_id FK
bigint mac_id FK
}
plan_target_devices {
bigint id PK
text label
text vendor
text model
text planned_role
}
plan_target_vlans {
bigint id PK
integer vlan_id
text label
bigint target_segment_id FK
text purpose
text status
}
plan_target_interfaces {
bigint id PK
bigint target_device_id FK
text name
text planned_role
}
plan_target_interface_configs {
bigint id PK
bigint target_interface_id FK
text mode
bigint access_target_vlan_id FK
bigint native_target_vlan_id FK
jsonb allowed_target_vlans
jsonb config_payload
}
migration_interface_mappings {
bigint id PK
bigint source_interface_id FK
bigint target_interface_id FK
text status
text mapping_source
integer confidence
boolean is_current
timestamptz superseded_at
}
migration_migration_notes {
bigint id PK
bigint interface_mapping_id FK
text note
text severity
}
Poznámka k diagramu:
- work.* a report.* nejsou v ER diagramu jako tabulky, protože půjde primárně o views.
- Device mapping není samostatná tabulka; bude odvozen přes report.device_mapping_summary.
- core.assets je evidenční vrstva pro významná zařízení za porty (viz sekce 6.3.4).
- plan.target_vlans je samostatná entita; current core.vlans a plan.target_vlans se porovnávají přes VLAN ID, ale nemají FK vazbu.
Tato sekce převádí dosavadní návrh do prvních konkrétních implementačních rozhodnutí.
Primární evidenční vrstva první verze bude postavená na těchto objektech:
core.devices
core.interfaces
Důvod:
Migrace se plánuje a kontroluje primárně na úrovni portů.
Port musí vždy patřit ke konkrétnímu zařízení.
Pozorování ze sítě musí být možné vztáhnout ke konkrétnímu portu.
Cílový plán musí být možné mapovat na konkrétní nový port.
Základní evidenční kotva tedy není pouze zařízení, ale dvojice:
device + interface
Podpůrná evidenční vrstva vysvětluje, co se za porty nachází nebo jak je síť logicky členěná.
Do první verze patří:
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
core.vlans
Tyto tabulky nejsou primární migrační jednotkou, ale jsou nutné pro odpovědi typu:
Jaké MAC adresy jsou za portem?
Jaké IP adresy jsou za portem?
Do jakých subnetů patří?
Jaké segmenty jsou za portem?
Které VLANy se portu týkají?
Pro migrační účely je nutné mít tabulku:
core.assets
Ta neeviduje každé zařízení v síti (to by bylo nereálné). Eviduje objekty, které mají význam pro člověka nebo migraci.
Příklady:
tiskárna
kamera
AP
server
virtualizační host
kritické koncové zařízení
neznámé zařízení k ověření
Smysl:
MAC/IP pozorování říká technickou stopu.
Asset evidence říká, co tato stopa znamená.
Proto core.assets pomáhá odpovědět nejen:
Co je za portem technicky vidět?
ale také:
Co je to za zařízení a má se při migraci hlídat?
Observed vrstva bude oddělená v obs.*.
Do první verze patří:
obs.import_batches
obs.mac_port_observations
obs.arp_observations
obs.interface_status_observations
obs.interface_config_observations
Observed tabulky nebudou reprezentovat definitivní stav. Budou reprezentovat časově označená pozorování.
Příklad:
obs.mac_port_observations
V čase T byla MAC M viděna na portu P.
obs.arp_observations
V čase T byla IP I spojena s MAC M.
Důležité pravidlo:
Observed data nejsou pravda sama o sobě. Jsou to vstupy pro interpretaci.
Cílový stav bude oddělený v plan.*.
Do první verze patří:
plan.target_devices
plan.target_interfaces
plan.target_interface_configs
Důvod oddělení:
Současný stav je rekonstruovaná realita.
Cílový stav je plán.
Plán může obsahovat vlastnosti, které ve staré infrastruktuře neexistují.
Cílový port může být předvyplněný podle současného portu, ale následně musí být ručně upravitelný.
Primární migrační tabulkou bude:
migration.interface_mappings
Ta bude vyjadřovat vztah:
current/core interface → plan/target interface
Device mapping nebude v první verzi samostatná tabulka. Bude odvozený z portového mapování přes view:
report.device_mapping_summary
Důvod:
Migrační rozhodnutí se prakticky děje na úrovni portů.
Vztah starý switch → nový switch lze většinou odvodit z množiny portových mapování.
Pro první SQL návrh se použije tato minimální sada tabulek:
core.devices
core.interfaces
core.mac_addresses
core.ip_addresses
core.subnets
core.segments
core.vlans
core.assets
core.asset_mac_addresses
core.asset_ip_addresses
obs.import_batches
obs.mac_port_observations
obs.arp_observations
obs.interface_status_observations
obs.interface_config_observations
plan.target_devices
plan.target_interfaces
plan.target_interface_configs
migration.interface_mappings
migration.migration_notes
První implementace nebude ještě řešit všechno. Jejím cílem je umožnit:
1. evidovat současné switche a porty,
2. importovat MAC/ARP/config/status pozorování,
3. evidovat významná zařízení za porty,
4. navrhnout cílové switche a porty,
5. mapovat starý port na nový port,
6. vytvořit první pracovní views pro kontrolu migrace.
Dalším krokem je navrhnout konkrétní sloupce těchto tabulek.
Priorita návrhu:
1. core.devices
2. core.interfaces
3. plan.target_devices
4. plan.target_interfaces
5. migration.interface_mappings
6. core.assets
7. obs.import_batches
8. obs.mac_port_observations
9. obs.arp_observations
Teprve po odsouhlasení sloupců bude vhodné vytvořit první SQL CREATE TABLE skript.
Tato sekce navrhuje konkrétní sloupce pro první sadu tabulek, které tvoří hlavní osu migrace.
Cílem není ještě vytvořit finální SQL, ale ujasnit, jaké informace musí model nést.
Účel:
Evidence současných / existujících síťových prvků, ke kterým se vztahují aktuální porty a pozorování.
Navržené sloupce:
id
technický primární klíč
label
lidský název zařízení; hlavní pracovní identifikátor
hostname
DNS/konfigurační hostname, pokud se liší od labelu
mgmt_ip
management IP adresa zařízení
vendor
výrobce, například Huawei, Cisco, MikroTik, UniFi
model
model zařízení
serial_number
sériové číslo, pokud je dostupné
role
pracovní role zařízení, například access_switch, distribution_switch, firewall
site
lokalita / zákazník / objekt
status
stav evidence zařízení, například active, planned_retirement, retired, unknown
source
zdroj založení záznamu, například manual, import, snmp, netbox
note
volná poznámka
created_at
updated_at
Pracovní poznámky:
- label by měl být unikátní v rámci první implementace.
- mgmt_ip může být unikátní, ale nemusí být povinná.
- status zde neznamená cílový plán, pouze stav současného evidovaného zařízení.
Účel:
Evidence současných / existujících portů a interfaců na aktuálních síťových prvcích.
Navržené sloupce:
id
technický primární klíč
device_id
vazba na core.devices
name
název portu/interface tak, jak je používán na zařízení
label
volitelný lidský popis nebo alias
interface_type
typ interface, například physical, vlan, lag, routed, loopback
port_role
pracovní role portu, například access, trunk, uplink, downlink, unused, unknown
admin_status
poslední známý administrativní stav, pokud je evidován
oper_status
poslední známý operační stav, pokud je evidován
native_vlan_id
volitelná vazba na core.vlans pro native/default/access VLAN
description
popis portu ze zařízení nebo ruční evidence
source
zdroj založení nebo poslední významné aktualizace záznamu
note
volná poznámka
created_at
updated_at
Důležité constrainty:
UNIQUE(device_id, name)
Pracovní poznámky:
- Port/interface je primární migrační jednotka.
- Port role je pracovní interpretace/evidence, nikoliv nutně přesný opis konfigurace.
- Detailní konfigurační pozorování patří do obs.interface_config_observations.
Účel:
Evidence plánovaných cílových síťových prvků nové infrastruktury.
Navržené sloupce:
id
technický primární klíč
label
lidský název cílového zařízení
hostname
plánovaný hostname
mgmt_ip
plánovaná management IP adresa, pokud je známá
vendor
plánovaný výrobce
model
plánovaný model
serial_number
sériové číslo, pokud je již známé
planned_role
plánovaná role zařízení, například access_switch, distribution_switch
site
lokalita / zákazník / objekt
migration_phase
plánovaná migrační fáze nebo etapa
status
stav cílového zařízení, například proposed, approved, ordered, installed, configured, migrated
note
volná poznámka
created_at
updated_at
Pracovní poznámky:
- target device nemusí fyzicky existovat v době založení záznamu.
- status zde popisuje stav plánovaného/cílového zařízení, ne současnou realitu.
- Vazba staré zařízení → nové zařízení se v první verzi neukládá přímo, ale odvozuje z mapování portů.
Účel:
Evidence plánovaných cílových portů/interfaců na cílových zařízeních.
Navržené sloupce:
id
technický primární klíč
target_device_id
vazba na plan.target_devices
name
plánovaný název portu/interface
label
volitelný lidský alias nebo pracovní popis
interface_type
typ interface, například physical, vlan, lag, routed, loopback
planned_port_role
plánovaná role portu, například access, trunk, uplink, downlink, unused, unknown
planned_description
plánovaný popis portu
migration_phase
plánovaná migrační fáze portu
status
stav cílového portu, například proposed, approved, configured, ready, migrated, blocked
note
volná poznámka
created_at
updated_at
Důležité constrainty:
UNIQUE(target_device_id, name)
Pracovní poznámky:
- Target interface je cílový bod migrace.
- Detailní cílová konfigurace portu patří do plan.target_interface_configs.
- Target interface může být předvyplněn podle current interface, ale musí zůstat ručně upravitelný.
Účel:
Evidence plánovaných cílových VLAN v nové infrastruktuře.
Důvod pro samostatnou evidenci cílových VLAN:
VLAN ID je technické číslo, které lze porovnat mezi současným a cílovým stavem.
Význam VLAN ale nemusí být automaticky stejný.
Cílová VLAN může mít nový název, nový účel, nový segment, jiný status nebo jiný migrační význam.
Navržené sloupce:
id
technický primární klíč
vlan_id
číslo VLAN; technický identifikátor v rozsahu 1–4094
label
plánovaný název VLAN
target_segment_id
volitelná vazba na core.segments, pokud cílová VLAN patří ke známému logickému segmentu
purpose
účel VLAN, například users, printers, cameras, management, voice, servers
status
stav cílové VLAN, například proposed, approved, configured, migrated, deprecated
note
volná poznámka
created_at
updated_at
Důležité constrainty:
UNIQUE(vlan_id)
Pracovní poznámky:
- VLAN ID lze použít pro porovnání current VLAN vs target VLAN.
- Shodné VLAN ID neznamená automaticky shodný význam.
- Pokud bude potřeba explicitně mapovat starou VLAN na cílovou VLAN, doplní se migration.vlan_mappings.
Účel:
Evidence plánované cílové konfigurace portu.
Navržené sloupce:
id
technický primární klíč
target_interface_id
vazba na plan.target_interfaces
mode
plánovaný režim portu, například access, trunk, routed, disabled
access_target_vlan_id
vazba na plan.target_vlans pro plánovanou access VLAN, pokud dává smysl
native_target_vlan_id
vazba na plan.target_vlans pro plánovanou native VLAN, pokud dává smysl
allowed_target_vlan_ids
JSONB nebo později samostatná vazební tabulka pro seznam povolených cílových VLAN
planned_description
plánovaný config description
config_payload
JSONB pro vendor-specific nebo strukturované detaily konfigurace
config_text
volitelný textový výstup/plán konfigurace
status
stav konfigurace, například draft, reviewed, approved, generated, applied
note
volná poznámka
created_at
updated_at
Pracovní poznámky:
- Cílová konfigurace portu odkazuje na plan.target_vlans, ne přímo na core.vlans.
- Pro první verzi je praktičtější použít kombinaci strukturovaných sloupců + JSONB.
- Pokud se práce s allowed VLAN ukáže jako důležitá, později se doplní samostatná tabulka plan.target_interface_allowed_vlans.
- Tato tabulka reprezentuje plán, nikoliv observed konfiguraci ze starého zařízení.
Účel:
Primární migrační vazba mezi současným portem a cílovým portem.
Navržené sloupce:
id
technický primární klíč
source_interface_id
vazba na core.interfaces; starý/current port
target_interface_id
vazba na plan.target_interfaces; nový/cílový port
status
stav mapování, například proposed, verified, ready, migrated, blocked, rejected
mapping_source
původ mapování, například manual, imported, name_match, port_order, ai_suggested
confidence
pracovní míra jistoty 0–100
requires_manual_review
příznak, že mapování musí člověk ověřit
blocking_reason
důvod blokace, pokud status = blocked
is_current
příznak, zda jde o aktuální (živé) rozhodnutí, nebo o historický záznam
superseded_at
čas, kdy bylo mapování nahrazeno novým rozhodnutím
superseded_reason
důvod nahrazení (například „špatný target port", „LAG redesign", „změna návrhu")
note
volná poznámka
created_at
updated_at
Důležité constrainty:
PARTIAL UNIQUE INDEX (source_interface_id) WHERE is_current = true
PARTIAL UNIQUE INDEX (target_interface_id) WHERE is_current = true
Pracovní poznámky:
- V daný čas je za jedním source portem aktivní nejvýše jedno mapování.
- V daný čas je za jedním target portem aktivní nejvýše jedno mapování.
- Historická rozhodnutí (rejecty, superseded návrhy) se nemažou, jen se přepne is_current = false.
- M:N případy (LAG, split, merge) první verze úmyslně neřeší; jejich řešení je otevřená otázka (sekce 9).
Potvrzená rozhodnutí:
1. V daný čas je vztah source interface → target interface nejvýše 1:1, ale model nese historii rozhodnutí.
2. Cílové VLANy budou evidované samostatně v plan.target_vlans.
3. VLAN ID bude možné používat pro technické porovnání současné a cílové VLAN.
4. Shodné VLAN ID ale nebude automaticky znamenat shodný význam.
5. M:N případy (LAG, split, merge) první verze neřeší – viz sekce 9.
Důsledky pro model:
migration.interface_mappings
bude mít partial UNIQUE(source_interface_id) WHERE is_current = true
bude mít partial UNIQUE(target_interface_id) WHERE is_current = true
bude mít sloupce is_current, superseded_at, superseded_reason
plan.target_interface_configs
bude odkazovat na plan.target_vlans
nebude přímo odkazovat na core.vlans
Tato sekce nahrazuje detailní rozpad otevřených rozhodnutí jednodušším pravidlem pro první implementaci.
Cíl první verze není vytvořit dokonalý relační model. Cíl první verze je vytvořit model, kterému půjde rozumět, který půjde naplnit daty a nad kterým půjde vytvořit první užitečné pohledy.
Pracovní pravidlo:
Pokud existuje složitější, ale čistší varianta a jednodušší, srozumitelnější varianta, první verze zvolí jednodušší variantu.
Pro první implementaci se nebudeme snažit hned řešit všechny možné hraniční případy.
Zjednodušená rozhodnutí:
1. Portové mapování bude v daný čas nejvýše 1:1, ale s historií.
Jeden aktivní záznam per source/target port přes is_current + partial unique index.
M:N (LAG) odložené k diskuzi (sekce 9).
2. Cílové VLANy budou v plan.target_vlans.
VLAN ID je číslo, podle kterého lze current a target VLAN porovnat.
3. Allowed VLANy na trunk portu budou zatím uložené jednoduše.
V první verzi jako text nebo JSONB v plan.target_interface_configs.
Samostatná vazební tabulka se doplní až tehdy, pokud to bude opravdu potřeba.
4. Statusy budou zatím obyčejný TEXT.
Hodnoty budeme používat konzistentně, ale nebudeme je hned tvrdě vynucovat přes CHECK constraint.
5. core.assets zatím ponecháme jako jednoduchou a volitelnou evidenci významných zařízení.
Ne jako plnohodnotnou CMDB.
6. migration.vlan_mappings zatím nezavádíme.
Current VLAN a target VLAN budeme nejdřív porovnávat přes VLAN ID.
Důvodem je srozumitelnost.
První verze má odpovědět hlavně na otázky:
Jaké staré zařízení a port řeším?
Co je za tím portem vidět?
Na jaký nový port se to má převést?
Jaká má být cílová konfigurace nového portu?
Je tento port připravený k migraci?
Pokud model hned rozdělíme do příliš mnoha pomocných tabulek, bude sice databázově čistší, ale hůř pochopitelný a hůř použitelný při prvním nasazení.
Pro první verzi stačí držet v hlavě tento obraz:
core.*
co dnes existuje
obs.*
co jsme v síti viděli
plan.*
co chceme v nové síti
migration.*
jak starý port mapujeme na nový port
report.*
co chceme vidět jako člověk
Detailní vrstvy work.* a derived.* zůstávají v návrhu, ale první implementace je nemusí hned fyzicky plnit tabulkami. Mohou začít jako SQL views.
1. core.devices + core.interfaces
evidují současné switche a porty.
2. obs.mac_port_observations + obs.arp_observations
ukládají, co bylo zjištěno ze sítě.
3. plan.target_devices + plan.target_interfaces + plan.target_interface_configs
popisují plán nové infrastruktury.
4. migration.interface_mappings
propojuje starý port s novým portem.
5. report views
ukazují člověku přehled: starý port, zjištěná realita, nový port, cílová konfigurace, stav migrace.
Na později odkládáme:
- samostatnou tabulku pro allowed VLANy,
- tvrdé CHECK constrainty pro všechny statusy,
- explicitní VLAN mapping,
- složité scoring/confidence modely,
- složité derived tabulky,
- plnohodnotnou CMDB nad core.assets.
Tyto části nejsou zahozené. Jen nejsou nutné pro první pochopitelnou verzi.
První implementace bude jednoduchá:
Eviduj staré switche a porty.
Importuj pozorování MAC/ARP/config/status.
Eviduj cílové switche a porty.
U portu drž jednoduchou cílovou konfiguraci.
Mapuj starý port na nový port.
Nad tím vytvoř první reportovací pohledy.
Teprve až se na reálných datech ukáže, že některá část nestačí, rozdělí se do čistší samostatné tabulky nebo vrstvy.
Tato sekce obsahuje první jednoduchý SQL návrh pro založení databázového modelu.
Cílem není pokrýt všechny budoucí varianty, ale vytvořit použitelný základ, který umožní:
- evidovat současné switche a porty,
- evidovat podpůrné objekty jako VLAN, subnety, segmenty, MAC a IP,
- ukládat pozorování MAC/ARP/config/status,
- evidovat cílová zařízení, porty a VLANy,
- držet jednoduchou cílovou konfiguraci portů,
- mapovat starý port na nový port,
- později nad tím vytvořit reportovací views.
Záměrná zjednodušení první verze:
- statusy jsou TEXT bez CHECK constraintů,
- allowed VLANy jsou v JSONB,
- device mapping se neukládá jako tabulka,
- VLAN mapping se zatím neukládá jako tabulka,
- derived tabulky se zatím nezavádí,
- složité confidence/scoring modely se zatím nezavádí.
-- ============================================================
-- SCHEMAS
-- ============================================================
CREATE SCHEMA IF NOT EXISTS core;
CREATE SCHEMA IF NOT EXISTS obs;
CREATE SCHEMA IF NOT EXISTS plan;
CREATE SCHEMA IF NOT EXISTS migration;
CREATE SCHEMA IF NOT EXISTS work;
CREATE SCHEMA IF NOT EXISTS report;
-- ============================================================
-- CORE: současná evidenční vrstva
-- ============================================================
CREATE TABLE core.devices (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
label TEXT NOT NULL UNIQUE,
hostname TEXT,
mgmt_ip INET,
vendor TEXT,
model TEXT,
serial_number TEXT,
role TEXT, -- allowed (pracovně): access_switch, distribution_switch, core_switch, firewall, router, other
site TEXT,
status TEXT, -- allowed: active, planned_retirement, retired, unknown
source TEXT, -- allowed (pracovně): manual, import, snmp, netbox, discovered
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.vlans (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
vlan_id INTEGER NOT NULL UNIQUE,
label TEXT,
purpose TEXT, -- allowed (pracovně): users, printers, cameras, management, voice, servers, guest, other
status TEXT, -- allowed: active, deprecated, planned
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.segments (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
label TEXT NOT NULL UNIQUE,
description TEXT,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.subnets (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
prefix CIDR NOT NULL UNIQUE,
label TEXT,
segment_id BIGINT REFERENCES core.segments(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.interfaces (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
device_id BIGINT NOT NULL REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
name TEXT NOT NULL,
label TEXT,
interface_type TEXT, -- allowed (pracovně): physical, vlan, lag, routed, loopback, sub_interface
port_role TEXT, -- allowed (pracovně): access, trunk, uplink, downlink, unused, unknown
admin_status TEXT, -- allowed: up, down, unknown
oper_status TEXT, -- allowed: up, down, unknown
native_vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
description TEXT,
source TEXT, -- allowed (pracovně): manual, import, snmp, discovered
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT core_interfaces_device_name_unique
UNIQUE (device_id, name)
);
CREATE TABLE core.mac_addresses (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
mac MACADDR NOT NULL UNIQUE,
label TEXT,
first_seen TIMESTAMPTZ,
last_seen TIMESTAMPTZ,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.ip_addresses (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
address INET NOT NULL UNIQUE,
label TEXT,
subnet_id BIGINT REFERENCES core.subnets(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
first_seen TIMESTAMPTZ,
last_seen TIMESTAMPTZ,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.assets (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
label TEXT NOT NULL,
asset_type TEXT, -- allowed (pracovně): printer, camera, ap, server, vm_host, voip_phone, endpoint, unknown
criticality TEXT, -- allowed: low, medium, high, critical
owner TEXT,
migration_watch BOOLEAN NOT NULL DEFAULT false,
last_verified_at TIMESTAMPTZ, -- kdy člověk naposledy potvrdil, že záznam odpovídá realitě
verified_by TEXT, -- kdo potvrdil (jméno nebo identifikátor)
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE core.asset_mac_addresses (
asset_id BIGINT NOT NULL REFERENCES core.assets(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
mac_id BIGINT NOT NULL REFERENCES core.mac_addresses(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (asset_id, mac_id)
);
CREATE TABLE core.asset_ip_addresses (
asset_id BIGINT NOT NULL REFERENCES core.assets(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
ip_address_id BIGINT NOT NULL REFERENCES core.ip_addresses(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
PRIMARY KEY (asset_id, ip_address_id)
);
-- ============================================================
-- OBS: observed / importní vrstva
-- ============================================================
CREATE TABLE obs.import_batches (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
source TEXT NOT NULL, -- volný popis zdroje, např. 'snmp-collector-v3', 'manual-csv-2026-05'
source_type TEXT, -- allowed (pracovně): snmp_mac, snmp_arp, ssh_config, ssh_status, netbox, manual, csv
device_id BIGINT REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
script_name TEXT,
script_version TEXT,
started_at TIMESTAMPTZ NOT NULL DEFAULT now(),
finished_at TIMESTAMPTZ,
status TEXT NOT NULL DEFAULT 'running', -- allowed: running, success, partial, failed
note TEXT
);
CREATE TABLE obs.mac_port_observations (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_id BIGINT REFERENCES obs.import_batches(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
observed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
device_id BIGINT REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
interface_id BIGINT REFERENCES core.interfaces(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
mac_id BIGINT NOT NULL REFERENCES core.mac_addresses(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
source TEXT,
raw_device TEXT,
raw_interface TEXT,
raw_mac TEXT,
raw_vlan TEXT,
raw_payload JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE obs.arp_observations (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_id BIGINT REFERENCES obs.import_batches(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
observed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
device_id BIGINT REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
interface_id BIGINT REFERENCES core.interfaces(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
ip_address_id BIGINT NOT NULL REFERENCES core.ip_addresses(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
mac_id BIGINT REFERENCES core.mac_addresses(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
source TEXT,
raw_device TEXT,
raw_interface TEXT,
raw_ip TEXT,
raw_mac TEXT,
raw_vlan TEXT,
raw_payload JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE obs.interface_status_observations (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_id BIGINT REFERENCES obs.import_batches(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
observed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
device_id BIGINT REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
interface_id BIGINT REFERENCES core.interfaces(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
admin_status TEXT,
oper_status TEXT,
speed BIGINT,
duplex TEXT,
source TEXT,
raw_payload JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE obs.interface_config_observations (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
batch_id BIGINT REFERENCES obs.import_batches(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
observed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
device_id BIGINT REFERENCES core.devices(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
interface_id BIGINT REFERENCES core.interfaces(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
mode TEXT,
access_vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
native_vlan_id BIGINT REFERENCES core.vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
allowed_vlans JSONB,
description TEXT,
config_text TEXT,
config_payload JSONB,
source TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ============================================================
-- PLAN: cílový plán nové infrastruktury
-- ============================================================
CREATE TABLE plan.target_devices (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
label TEXT NOT NULL UNIQUE,
hostname TEXT,
mgmt_ip INET,
vendor TEXT,
model TEXT,
serial_number TEXT,
planned_role TEXT, -- allowed (pracovně): access_switch, distribution_switch, core_switch, firewall, router, other
site TEXT,
migration_phase TEXT, -- volný text pro vlnu/fázi migrace, např. 'wave_1', 'pilot'
status TEXT, -- allowed: proposed, approved, ordered, installed, configured, migrated
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE plan.target_vlans (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
vlan_id INTEGER NOT NULL UNIQUE,
label TEXT,
target_segment_id BIGINT REFERENCES core.segments(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
purpose TEXT, -- allowed (pracovně): users, printers, cameras, management, voice, servers, guest, other
status TEXT, -- allowed: proposed, approved, configured, migrated, deprecated
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE plan.target_interfaces (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
target_device_id BIGINT NOT NULL REFERENCES plan.target_devices(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
name TEXT NOT NULL,
label TEXT,
interface_type TEXT, -- allowed (pracovně): physical, vlan, lag, routed, loopback, sub_interface
planned_port_role TEXT, -- allowed (pracovně): access, trunk, uplink, downlink, unused, unknown
planned_description TEXT,
migration_phase TEXT,
status TEXT, -- allowed: proposed, approved, configured, ready, migrated, blocked
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
CONSTRAINT plan_target_interfaces_device_name_unique
UNIQUE (target_device_id, name)
);
CREATE TABLE plan.target_interface_configs (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
target_interface_id BIGINT NOT NULL REFERENCES plan.target_interfaces(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
mode TEXT, -- allowed: access, trunk, routed, disabled
access_target_vlan_id BIGINT REFERENCES plan.target_vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
native_target_vlan_id BIGINT REFERENCES plan.target_vlans(id)
ON UPDATE CASCADE
ON DELETE SET NULL,
allowed_target_vlans JSONB, -- JSON pole VLAN ID nebo plan.target_vlans.id (volně, viz sekce 6.6.5)
planned_description TEXT,
config_payload JSONB,
config_text TEXT,
status TEXT, -- allowed: draft, reviewed, approved, generated, applied
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- ============================================================
-- MIGRATION: mapování současného a cílového stavu
-- ============================================================
CREATE TABLE migration.interface_mappings (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
source_interface_id BIGINT NOT NULL REFERENCES core.interfaces(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
target_interface_id BIGINT NOT NULL REFERENCES plan.target_interfaces(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
status TEXT, -- allowed: proposed, verified, ready, migrated, blocked, rejected
mapping_source TEXT, -- allowed (pracovně): manual, imported, name_match, port_order, ai_suggested
confidence INTEGER, -- 0–100; pracovní jistota
requires_manual_review BOOLEAN NOT NULL DEFAULT false,
blocking_reason TEXT,
is_current BOOLEAN NOT NULL DEFAULT true, -- false = historický záznam (viz superseded_*)
superseded_at TIMESTAMPTZ, -- kdy bylo mapování nahrazeno
superseded_reason TEXT, -- proč bylo nahrazeno (např. 'redesign', 'wrong target', 'LAG merge')
note TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- V jednu chvíli je za daný source/target port aktivní nejvýše jedno mapování.
-- Historická (is_current = false) mapování se nepočítají do unikátnosti.
CREATE UNIQUE INDEX migration_interface_mappings_source_active
ON migration.interface_mappings(source_interface_id)
WHERE is_current = true;
CREATE UNIQUE INDEX migration_interface_mappings_target_active
ON migration.interface_mappings(target_interface_id)
WHERE is_current = true;
CREATE TABLE migration.migration_notes (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
interface_mapping_id BIGINT REFERENCES migration.interface_mappings(id)
ON UPDATE CASCADE
ON DELETE CASCADE,
severity TEXT, -- allowed: info, warning, error, critical
note TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by TEXT
);
-- ============================================================
-- INDEXES
-- ============================================================
CREATE INDEX idx_core_interfaces_device_id
ON core.interfaces(device_id);
CREATE INDEX idx_core_interfaces_native_vlan_id
ON core.interfaces(native_vlan_id);
CREATE INDEX idx_core_subnets_segment_id
ON core.subnets(segment_id);
CREATE INDEX idx_core_subnets_vlan_id
ON core.subnets(vlan_id);
CREATE INDEX idx_core_ip_addresses_subnet_id
ON core.ip_addresses(subnet_id);
CREATE INDEX idx_obs_import_batches_device_id
ON obs.import_batches(device_id);
CREATE INDEX idx_obs_mac_port_observations_observed_at
ON obs.mac_port_observations(observed_at DESC);
CREATE INDEX idx_obs_mac_port_observations_interface_id
ON obs.mac_port_observations(interface_id);
CREATE INDEX idx_obs_mac_port_observations_mac_id
ON obs.mac_port_observations(mac_id);
CREATE INDEX idx_obs_arp_observations_observed_at
ON obs.arp_observations(observed_at DESC);
CREATE INDEX idx_obs_arp_observations_ip_address_id
ON obs.arp_observations(ip_address_id);
CREATE INDEX idx_obs_arp_observations_mac_id
ON obs.arp_observations(mac_id);
CREATE INDEX idx_obs_interface_status_observations_interface_id
ON obs.interface_status_observations(interface_id);
CREATE INDEX idx_obs_interface_config_observations_interface_id
ON obs.interface_config_observations(interface_id);
CREATE INDEX idx_plan_target_interfaces_device_id
ON plan.target_interfaces(target_device_id);
CREATE INDEX idx_plan_target_interface_configs_interface_id
ON plan.target_interface_configs(target_interface_id);
-- Indexy idx_migration_interface_mappings_source/target_interface_id
-- nejsou potřeba samostatně - jsou pokryté partial unique indexy
-- migration_interface_mappings_source_active a _target_active výše.První SQL návrh je záměrně jednoduchý, ale obsahuje několik vědomě zavedených mechanismů, které dříve nebyly dořešené.
- současná zařízení a porty,
- současné VLANy, subnety a segmenty,
- MAC a IP identity,
- významná sledovaná zařízení přes core.assets, včetně sledování čerstvosti ověření
(last_verified_at, verified_by),
- pravidla zakládání identit (sekce 5.1.4): co skript smí auto-založit a co ne,
- observed MAC za portem,
- observed ARP vazby,
- observed interface status,
- observed interface config,
- cílová zařízení,
- cílové porty,
- cílové VLANy,
- cílová konfigurace portu,
- mapování starý port → nový port,
- historie rozhodnutí o mapování přes is_current + partial unique indexy,
- dokumentace povolených hodnot status sloupců přímo v SQL.
- plnohodnotný lifecycle systém,
- kompletní CMDB,
- explicitní mapping starý switch → nový switch,
- explicitní mapping stará VLAN → nová VLAN,
- samostatnou relační tabulku allowed VLAN,
- M:N portová mapování (LAG, split, merge) – viz sekce 9,
- automatické generování finálních konfigurací,
- složité rozhodování o aktuálním stavu,
- historizaci ručních změn nad rámec mapování,
- fyzickou vrstvu (kabely, patch panely, pozice v rozvaděči) – viz sekce 9.2.
Dalším krokem po vytvoření tabulek budou první views:
work.current_mac_locations
work.current_ip_mac_bindings
work.current_port_segments
report.segments_behind_port
report.port_migration_overview
report.device_mapping_summary
Tento dokument zatím nedefinuje finální implementaci. Je potřeba doplnit zejména:
1. Konkrétní sloupce minimálních core tabulek.
2. Konkrétní sloupce minimálních observation tabulek.
3. Konkrétní sloupce plan tabulek.
4. Konkrétní sloupce migration tabulek.
5. Pravidla normalizace identit.
6. Časová okna pro aktuální stav.
7. Pravidla důvěryhodnosti zdrojů.
8. Role portů a jejich vliv na interpretaci.
9. Kdy použít SQL view a kdy derived tabulku.
10. Jak řešit ruční override.
11. Jak řešit konflikty.
12. Jaké reportovací pohledy jsou potřeba jako první.
Tato kapitola popisuje skripty, které ve fázi 1 (sběr dat před výměnou hardware) plní obs.* a podpůrné core.* tabulky. Cílem kapitoly je definovat hranice, datový kontrakt a implementační konvence, ne konkrétní implementaci.
Skripty první fáze dělají jednu věc: sbírají data ze síťových zdrojů a ukládají je do databáze podle pravidel popsaných v dokumentu. Nic víc.
Co skripty nedělají:
- neinterpretují, co data znamenají (to je úloha views work.* a derived.*),
- nevytváří reporty (to je úloha report.*),
- nezakládají paralelní struktury mimo dokumentovaný model,
- nezpracovávají rozhodování o cílové infrastruktuře (plan.*, migration.*).
Jak konkrétně skript komunikuje se zařízením (SNMP verze, MIBy, autentizace, normalizace názvů, vendor-specific zvláštnosti) není součástí dokumentu. To je věc implementace a může se v čase měnit.
Datový kontrakt (závazné). Každý skript, který ukládá data do databáze, musí dodržet pravidla v této sekci. Porušení ohrozí integritu dat. Vymáhá se reviewem schématu a observed dat.
K1. Žádné paralelní struktury. Skript zapisuje výhradně do tabulek popsaných v tomto dokumentu (kapitola 4 a 6.7). Skript nevytváří vlastní pomocné tabulky, vlastní schémata, pomocné soubory v databázi, ani sdílený stav mimo databázi.
K2. Pravidla zakládání identit.
Skript respektuje pravidla v sekci 5.1.4. Co dokument nepovoluje auto-založit (typicky core.devices), skript nezakládá.
K3. Raw data u každého zápisu v obs.*.
Každý řádek, který skript vytváří v obs.*, obsahuje raw hodnoty zdroje v polích raw_* (např. raw_interface, raw_mac, raw_payload). Důvod: dohledatelnost při ladění a možnost zpětně zrekonstruovat, co zdroj reálně řekl.
K4. Skript pracuje v kontextu batche.
Každý import začíná vytvořením záznamu v obs.import_batches (status 'running'). Každý observed záznam má batch_id. Na konci skript batch uzavírá se statusem:
'success' všechno proběhlo, data validní
'partial' proběhla jen část (např. timeout u některých zařízení)
'failed' skript selhal, observed data v tomto batchi nejsou důvěryhodná
Žádné observation bez batch_id. Žádný batch ve stavu 'running' po skončení skriptu.
K5. Spojování dat zachovává raw stopu.
Pokud skript před zápisem spojuje data z více zdrojů (např. SNMP ifTable + ifAlias, nebo joinuje MAC tabulku s VLAN kontextem), výsledné spojené hodnoty zapíše do strukturovaných polí, ale i tak ukládá raw podklady do raw_*. Skript nedrží spojený výsledek jako jedinou pravdu.
K6. Skript selhává viditelně.
Při neznámém zařízení, selhání ověření identity, nebo nečekané chybě skript končí s batch status 'failed' (nebo 'partial', pokud část dat je validní). Skript nesmí tiše ignorovat chyby ani maskovat selhání úspěchem.
Implementační konvence (doporučené). Sekce popisuje očekávané vlastnosti kódu skriptů, ne dat. Porušení neohrozí integritu DB, ale ohrozí dlouhodobou udržovatelnost. Vymáhá se reviewem kódu.
M1. Jeden krok workflow = jeden modul. Každý logický krok (otevření batche, dotaz na zařízení, normalizace dat, upsert do DB, uzavření batche) je samostatně volaná funkce nebo modul. Cíl: každý krok lze samostatně otestovat a verifikovat.
M2. Primitivní datové struktury.
Skript pracuje s primitivními Python strukturami: list, dict, tuple, případně dataclass. Skript nepoužívá pandas DataFrame, numpy arrays, ORM (SQLAlchemy modely, Django ORM), ani jiné komplexní data containery. Cíl: čitelnost a snadná dohledatelnost toho, co skript dělá.
M3. Čitelný kód, žádné mini-frameworky. Kód je psán pro člověka, který ho bude číst za rok. Krátké funkce, popisná jména, žádné chytrácké zkratky. Skript nesmí budovat vlastní abstrakce nad SNMP knihovnami, plugin architektury, ani interní DSL. Pokud má skript dělat víc různých věcí, je to víc různých skriptů.
M4. Žádná sdílená knihovna mezi skripty (v první verzi). Skripty první fáze jsou samostatné. Pokud se ukáže, že se nějaká logika opravdu opakuje (typicky open/close batche), refaktor přijde až po dokončení první funkční verze. Předčasná abstrakce = předčasná komplexita.
Tato sekce popisuje co skripty dělají z pohledu modelu. Jak konkrétně (SNMP MIBy, knihovny, vendor specifika) není součástí dokumentu.
discover_interfaces
Vstup: identifikátor zařízení v core.devices.
Akce: zjistí seznam interface na zařízení, normalizuje na kanonický tvar,
upsert do core.interfaces. Aktualizuje doplňková pole
(např. snmp_if_index, snmp_if_name, label).
Výstup: počet nových / aktualizovaných záznamů, seznam neklasifikovaných
položek pro ruční revizi.
collect_mac_table
Vstup: identifikátor zařízení v core.devices.
Akce: stáhne MAC adresové tabulky ze zařízení, normalizuje MAC adresy,
propojí s core.interfaces (přes pravidla 5.1.4), zapíše do
obs.mac_port_observations. Auto-založí MAC adresy v core.mac_addresses,
pokud zatím neexistují.
Výstup: počet zápisů, počet auto-založených MAC, případné konflikty.
collect_arp_table
Vstup: identifikátor zařízení v core.devices (typicky firewall/router).
Akce: stáhne ARP tabulku, normalizuje IP a MAC, propojí s core,
zapíše do obs.arp_observations. Auto-založí IP adresy v
core.ip_addresses, pokud zatím neexistují.
Výstup: počet zápisů, počet auto-založených IP, případné nesoulady.
verify_device
Vstup: identifikátor zařízení v core.devices.
Akce: připojí se na zařízení, ověří identitu proti evidenci (typicky
porovnáním hostname, případně dalších atributů). Zapíše batch
se statusem 'success' (identita souhlasí) nebo 'failed' (neshoda).
Výstup: výsledek ověření. Data sama nezapisuje (jen meta-záznam v batchi).
- batch zůstává v DB se statusem 'failed' nebo 'partial';
to je samo o sobě informace (data quality issue),
- raw_* pole zachovávají to, co zdroj řekl, i když interpretace selhala,
- skript loguje, co se stalo, ale primárně reportuje selhání
přes status batche, ne přes side-channel (e-mail, slack atp.),
- žádný retry uvnitř skriptu; pokud se má import opakovat,
je to věc operátora nebo nadřazené orchestrace.
Tato sekce ukazuje na konkrétním (zjednodušeném) příkladu, jak data tečou modelem od pozorování až do reportu. Cílem je otestovat, zda model unese realistický scénář, a sloužit jako návod pro implementaci skriptů.
Současný switch:
label: huawei-sw01
vendor: Huawei
model: S5720-28X-LI
role: access_switch
site: HQ
status: active
Porty na switchi:
Gi0/0/1 access port, uživatelská VLAN 10
Gi0/0/2 access port, uživatelská VLAN 10
Gi0/0/3 access port, VLAN 20 (tiskárny)
Gi0/0/4 nepoužívaný
Gi0/0/24 uplink na distribuční switch, trunk
Cílový switch po výměně:
label: cisco-sw01
vendor: Cisco
model: C9200L-24P
role: access_switch
Operátor založí současné i cílové zařízení. Pro porty první verze předpokládá, že je založí buď ručně, nebo automaticky první import.
core.devices
id=1 label='huawei-sw01' vendor='Huawei' status='active' source='manual'
plan.target_devices
id=1 label='cisco-sw01' vendor='Cisco' status='proposed'
core.vlans (založené buď ručně, nebo discoverem)
id=1 vlan_id=10 label='users' status='active'
id=2 vlan_id=20 label='printers' status='active'
plan.target_vlans
id=1 vlan_id=10 label='users' status='proposed'
id=2 vlan_id=20 label='printers' status='proposed'
Skript se připojí ke switchi, stáhne MAC tabulku a uloží do obs.*.
obs.import_batches
id=42 source='snmp-collector-v1' source_type='snmp_mac'
device_id=1 started_at='2026-05-23 09:00:00'
status='running'
Při importu skript narazí na MAC, kterou ještě nezná: 'aa:bb:cc:11:22:33'.
Podle pravidel 5.1.4 ji auto-založí:
core.mac_addresses
id=101 mac='aa:bb:cc:11:22:33' first_seen='2026-05-23 09:00:00'
obs.mac_port_observations
id=1001 batch_id=42 observed_at='2026-05-23 09:00:00'
device_id=1 interface_id=??(Gi0/0/1)
mac_id=101 vlan_id=1
raw_mac='AA-BB-CC-11-22-33' raw_vlan='10'
Pokud interface Gi0/0/1 ještě v core.interfaces neexistuje,
skript ji podle pravidel 5.1.4 také auto-založí:
core.interfaces
id=11 device_id=1 name='Gi0/0/1' source='discovered'
Skript ukončí dávku:
obs.import_batches.id=42 finished_at='2026-05-23 09:00:15' status='success'
Druhý skript stáhne ARP tabulku z firewallu, který má L3 interface v VLAN 10.
obs.import_batches
id=43 source='fw-arp-collector' source_type='snmp_arp'
device_id=99(firewall)
Skript najde IP, kterou nezná: '10.0.10.50' v subnetu 10.0.10.0/24.
core.ip_addresses
id=201 address='10.0.10.50' subnet_id=??(10.0.10.0/24)
first_seen='2026-05-23 09:01:00'
obs.arp_observations
id=2001 batch_id=43 observed_at='2026-05-23 09:01:00'
device_id=99(firewall)
ip_address_id=201 mac_id=101 vlan_id=1
raw_ip='10.0.10.50' raw_mac='AA-BB-CC-11-22-33'
Operátor v UI nebo přes import doplní, že MAC aa:bb:cc:11:22:33 patří tiskárně.
core.assets
id=301 label='Printer HQ-Sales-01' asset_type='printer'
criticality='medium' migration_watch=true
last_verified_at='2026-05-23 10:00:00' verified_by='admin'
core.asset_mac_addresses
asset_id=301 mac_id=101
core.asset_ip_addresses
asset_id=301 ip_address_id=201
Poznámka: scénář ukazuje, že tiskárna byla v MAC tabulce viděna na portu Gi0/0/1, ale operátor ji eviduje – to znamená, že buď tiskárna byla přepojena na port 1 (v evidenci je u portu 3), nebo evidence neodpovídá realitě. Tohle je přesně typ konfliktu, který má model zachytit, ne maskovat.
plan.target_interfaces
id=51 target_device_id=1 name='Gi1/0/1' status='proposed'
id=52 target_device_id=1 name='Gi1/0/2' status='proposed'
id=53 target_device_id=1 name='Gi1/0/3' status='proposed'
id=54 target_device_id=1 name='Gi1/0/4' status='proposed'
id=74 target_device_id=1 name='Gi1/0/24' status='proposed'
plan.target_interface_configs
id=1001 target_interface_id=51 mode='access'
access_target_vlan_id=1 status='draft'
id=1002 target_interface_id=52 mode='access'
access_target_vlan_id=1 status='draft'
id=1003 target_interface_id=53 mode='access'
access_target_vlan_id=2 status='draft'
... atd.
migration.interface_mappings
id=1 source_interface_id=11(Gi0/0/1) target_interface_id=51(Gi1/0/1)
status='proposed' mapping_source='port_order'
confidence=80 is_current=true
id=2 source_interface_id=12(Gi0/0/2) target_interface_id=52(Gi1/0/2)
status='proposed' mapping_source='port_order'
confidence=80 is_current=true
... atd.
Operátor zjistí, že port Gi0/0/3 (tiskárny) chce v nové infrastruktuře přesunout na Gi1/0/10 místo Gi1/0/3 kvůli novému kabeláži.
-- původní mapování se zaarchivuje
UPDATE migration.interface_mappings
SET is_current = false,
superseded_at = now(),
superseded_reason = 'kabeláž – přesun tiskáren na Gi1/0/10'
WHERE id = 3;
-- nové mapování se založí
INSERT INTO migration.interface_mappings
(source_interface_id, target_interface_id, status, mapping_source,
confidence, is_current)
VALUES
(13, 60, 'proposed', 'manual', 95, true);
Partial unique index migration_interface_mappings_source_active zajistí, že současně nemůže existovat dvě aktivní mapování pro Gi0/0/3. Historický záznam zůstane uložený.
report.segments_behind_port pro Gi0/0/3:
device: huawei-sw01
interface: Gi0/0/3
target_device: cisco-sw01
target_interface: Gi1/0/10 (po změně z Gi1/0/3)
mac_count: 1
ips: 10.0.10.50
segments: printers
assets: Printer HQ-Sales-01 (verified 2026-05-23)
mapping_status: proposed
flags: none
- pozorování (obs.*) nezná „pravdu", jen časově označená tvrzení;
- pravidla 5.1.4 fungují: MAC, IP, interface se auto-založí, device ne;
- core.assets překlene mezi technickou stopou a lidským významem;
- historie mapování drží předchozí návrhy bez ztráty auditu;
- partial unique index brání kolizi aktivních mapování;
- konflikty (port 1 vs port 3) se ukázaly v datech, ne ve výjimce skriptu.
Tato sekce obsahuje koncepční otázky, kde rozhodnutí ovlivní strukturu modelu (přidání tabulek, změna constraintů, nový sloupec). Stojí za to o nich mluvit, než se začne psát kód, ale není to nutné mít vyřešené před první implementací.
Implementační otázky (jak konkrétně se zachází s názvy portů, jak se zařízení identifikuje, atd.) jsou v samostatné sekci 10.
První verze umí v daném čase pouze 1:1 mapování (přes partial unique index na is_current = true).
V reálu existují případy:
- 4 fyzické porty na starém switchi tvoří LAG → 1 fyzický uplink na novém,
- 2 staré switche se slučují do 1 stack/VSS na novém,
- 1 starý port se rozpadá do více virtuálních interfaců.
Možné varianty řešení:
Varianta A: zavést logical_interface
Vrstva nad fyzickými porty: LAG je logický interface s vazbou na členské porty.
Migrační mapování běží na úrovni logical_interface, ne fyzických portů.
Plus: čistší abstrakce. Mínus: další tabulka, další vrstva.
Varianta B: zavést mapping_group
Group_id v migration.interface_mappings, jedna group = jedno logické mapování,
members přes více řádků.
Plus: minimální změna schématu. Mínus: kardinalita constraintů se ztratí.
Varianta C: počkat
Sledovat, jak často LAG case nastane v reálné migraci.
Pokud zřídka, řešit ad-hoc přes migration_notes.
Plus: žádná změna. Mínus: dluh.
Doporučení: počkat na první LAG case v reálné migraci, pak se rozhodnout mezi A a B. C zatím stačí.
Model je logicky-only. V reálné migraci je často 80 % práce „najít správný kabel". Pokud se to neřeší v tomto modelu, lidé povedou paralelní Excel, který se rozejde s realitou.
Možnosti:
Varianta A: nic, řeší se mimo
Akceptovat, že fyzická vrstva žije v patch panel dokumentaci.
Plus: jednoduché. Mínus: dva zdroje pravdy.
Varianta B: minimální evidence cabling
Přidat core.cables (cable_id, label, source_endpoint, target_endpoint, length, type).
Endpoint je buď interface, nebo patch panel port.
Plus: jeden zdroj pravdy. Mínus: nová oblast modelu.
Varianta C: free-text na interface
Přidat core.interfaces.physical_location nebo cable_label.
Plus: triviální. Mínus: nestrukturované, neauditovatelné.
Otázka pro tebe: jak moc je fyzická vrstva součástí této migrace? Pokud jde o site v jedné serverovně s krátkými kabely a operátoři vědí, kde co je, varianta A stačí. Pokud jde o multi-rack instalaci, varianta B se vyplatí.
Pravidla 5.1.4 říkají, že VLANy se auto-zakládají. Otázka: opravdu?
Pro:
- VLAN ID je technicky jednoznačná identita,
- discovered VLAN se stejně musí někam zapsat,
- operátor potřebuje vidět, jaké VLANy v síti reálně jsou.
Proti:
- špatně nakonfigurovaná zařízení mohou „discoverovat" desítky náhodných VLAN ID,
- core.vlans by se mohly zaplnit šumem,
- VLAN má často business význam, který skript nezná.
Možná varianta: discovered VLANy ukládat v obs.*, ale do core.vlans se přesouvat až po ručním schválení. To je čistší, ale komplikuje to import.
Doporučení: pro první verzi auto-zakládat, ale dát do core.vlans indikátor source = 'discovered', aby šly snadno najít a ověřit. Pokud se ukáže šum, zpřísnit.
Současný model má migration_phase TEXT na target devices a interfaces, ale nemá strukturu pro vlny migrace a jejich závislosti.
Reálný scénář:
- ve vlně 1 se migruje switch A (přístupový),
- vlna 2 závisí na hotové vlně 1 (B navazuje na A přes uplink),
- v každé vlně je window (sobota 22:00–04:00),
- VoIP a kamery mají vlastní okna.
Možná struktura:
migration.waves
id, label, planned_start, planned_end, status
migration.wave_dependencies
wave_id, depends_on_wave_id
migration.interface_mappings.wave_id
vazba mapování na vlnu
Otázka: bude tahle konkrétní migrace probíhat ve vlnách, nebo „big bang"? Pokud big bang, sekce 9.4 se odkládá.
V obs.* se neukládá konec platnosti pozorování. Pokud MAC dnes není vidět na portu, neexistuje záznam „nevidíme ji od T". Aktuálnost se odvozuje z observed_at.
Tohle pro první verzi funguje. Ale při ladění bude pravděpodobně potřeba odpovědět:
- kdy byla MAC X naposledy vidět?
- kdy se z portu Y úplně ztratila?
- jak dlouho je port Z prázdný?
Možná pole last_not_seen_at nebo samostatná tabulka obs.absence_observations – ale to už je třetí úroveň interpretace. Doporučení: počkat, řešit přes work views.
Tato sekce je seznam otázek, na které dokument záměrně neodpovídá, ale které musí každá implementace skriptů nějak vyřešit. Není to seznam problémů – je to seznam míst, kde implementace má prostor pro vlastní rozhodnutí, a kde se nemá hledat odpověď v dokumentu.
Pozor. Toto je sekce pro implementátora, ne pro skript. Není to datový kontrakt. Žádná z odpovědí níže neovlivní strukturu databáze – pouze způsob, jakým k ní skripty přistupují.
Stejný fyzický port může být v různých kontextech pojmenován různě:
SNMP ifName: "GigabitEthernet1/0/1"
SNMP ifDescr: "GigabitEthernet1/0/1"
CLI 'show int br': "Gi1/0/1"
LLDP neighbor: "Gi1/0/1"
Operátorský label: "Uplink to FW1"
Pravidlo core.interfaces.name jako kanonická forma neříká, jaká forma to konkrétně je. Implementace musí:
- zvolit konkrétní kanonickou formu (typicky dlouhá SNMP
ifName), - normalizovat raw názvy ze všech zdrojů na tuto formu,
- raw hodnoty ukládat do
raw_interfacevobs.*, - udržovat tuto konvenci napříč všemi skripty.
Skript při importu dostává device_id (přes label v core.devices). Po připojení k zařízení musí ověřit, že mluví se správnou identitou. Implementace musí rozhodnout:
- co konkrétně porovnává (hostname přes
sysName, sériové číslo přesentPhysicalSerialNum, kombinaci), - jak se chová při neshodě (typicky: batch status
'failed', žádné observed záznamy), - co dělá, když evidence nemá s čím srovnávat (nový device, prázdný
hostnameaserial_number).
core.interfaces.name je primární klíč (spolu s device_id), ale jeho stabilita závisí na konkrétním zařízení:
Cisco IOS / IOS-XE: ifName stabilní, ifIndex stabilní s 'snmp-server ifindex persist'
Huawei VRP: ifName stabilní, ifIndex obvykle stabilní
MikroTik RouterOS: ifName lze v configu přejmenovat (admin to udělá)
Ubiquiti UniFi: ifName obvykle stabilní, ale verze firmwaru mění chování
Implementace musí mít strategii, co se stane, když se pozorovaný ifName na zařízení změní (typicky přejmenováním admina). Možnosti:
- detekovat změnu (stejný
ifIndex, novýifName) a logovat jako data quality issue, - zachovat původní
core.interfaces.namea nový tvar uložit jen dosnmp_if_name, - nový tvar přijmout jako kanonický (riskantní – ztratí se historická pozorování).
SNMP poskytuje MAC tabulky přes různé MIBy s různou strukturou:
BRIDGE-MIB::dot1dTpFdbTable starší, MAC + port, bez VLAN
Q-BRIDGE-MIB::dot1qTpFdbTable novější, MAC + port + VLAN
Cisco IOS legacy: BRIDGE-MIB per-VLAN přes community indexing
(community@vlan-id)
Implementace collect_mac_table musí pro každý typ zařízení zvolit správnou cestu. Dokument neříká kterou – jen to, že výsledek musí být zapsán do obs.mac_port_observations s odpovídajícím vlan_id (nebo NULL, pokud zdroj VLAN neposkytuje).
SNMP ifTable vrací více než jen fyzické porty: VLAN interfaces, loopbacky, tunely, interní virtuální interfaces. Pro účely této evidence:
- relevantní pro MAC/ARP analýzu jsou
physical,lag(případněsubinterface), vlanaroutedjsou relevantní u L3 zařízení (firewall, router) pro ARP kontext,loopback,tunnel,othertypicky balast.
Implementace discover_interfaces musí rozhodnout, jak mapuje SNMP ifType na core.interfaces.interface_type. Filtrace „co je balast" je pak věc reportovacích views, ne importu (model ukládá vše s odpovídající kategorií).
Skripty potřebují credentials pro SNMP přístup (community string pro v2c, user/auth/priv pro v3). Implementace musí rozhodnout:
- kde credentials žijí (env proměnné, samostatný config soubor, vault),
- jak jsou předány skriptu (parametr, env, soubor),
- co dělá skript, když credentials chybí (selhání s jasnou hláškou),
- co dělá s credentials v logu (nikdy je nesmí logovat).
Dokument nepředpokládá, že credentials jsou v databázi. Mohou tam být v budoucí samostatné šifrované tabulce, ale to není první verze.
Dokument nepředepisuje:
- jazyk implementace (Python je doporučen kvůli SNMP knihovnám a čitelnosti),
- konkrétní SNMP knihovnu (
pysnmp,easysnmp, shell wrappery kolemsnmpwalk), - způsob připojení k DB (
psycopg,psycopg2, něco jiného), - způsob spouštění (ručně, cron, systemd timer, něco jiného).
Pravidla v sekci 7.2 (datový kontrakt) a 7.3 (implementační konvence) jsou jediná omezení.