diff --git a/schemas/README.md b/schemas/README.md index f753c89..ce54fc2 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -1,71 +1,162 @@ # Infrahub Schema for EVPN-VXLAN Fabric -This directory contains the Infrahub schema definitions for modeling an EVPN-VXLAN fabric. The schema is designed to represent the [arista-evpn-vxlan-clab](https://gitea.arnodo.fr/Damien/arista-evpn-vxlan-clab) topology. +This directory contains the Infrahub schema definitions for modeling an EVPN-VXLAN fabric. The schema is designed to represent the [overlaid.net reference topology](https://overlaid.net/2019/01/27/arista-bgp-evpn-configuration-example/) (2 spines, 8 leafs in 4 MLAG pairs). ## Schema Files -| File | Description | -|------|-------------| -| `base.yml` | Core infrastructure: Device, Interface types, IP Address, Platform, Site | -| `vlan_vxlan.yml` | VLAN, VNI, VTEP, EVPN Instance | -| `vrf.yml` | VRF, Route Target, VRF assignments | -| `bgp.yml` | Autonomous System, BGP Config, Peer Groups, Sessions | -| `mlag.yml` | MLAG Domain, Peer Config, MLAG Interfaces | -| `extensions.yml` | Fabric, Underlay Links, Host Connections | +| File | Nodes | Description | +|------|-------|-------------| +| `base.yml` | Device, InterfaceEthernet, InterfaceLoopback, InterfaceVlan, InterfaceLag, IPAddress, Site, Platform | Core infrastructure and generic Interface | +| `bgp.yml` | AutonomousSystem, BGPRouterConfig, BGPPeerGroup, BGPSession, BGPAddressFamily | BGP routing configuration | +| `vlan_vxlan.yml` | VLAN, VNI, VTEP, VlanVniMapping, EVPNInstance | Layer 2 overlay and VXLAN tunneling | +| `vrf.yml` | VRF, RouteTarget, VRFDeviceAssignment | VRF and L3VNI configuration | +| `mlag.yml` | MlagDomain, MlagPeerConfig, MlagInterface | MLAG domain and peer configuration | +| `extensions.yml` | Fabric, UnderlayLink, HostConnection | Fabric topology and connectivity | ## Entity Relationship Diagram ``` -┌─────────────────────────────────────────────────────────────────────────────┐ -│ FABRIC TOPOLOGY │ -└─────────────────────────────────────────────────────────────────────────────┘ + ┌──────────────┐ + │ InfraFabric │ + └──────┬───────┘ + ┌───────────┼───────────┐ + ▼ ▼ ▼ + ┌────────────┐ ┌──────────┐ ┌──────────────────┐ + │LocationSite│ │InfraAS │ │InfraUnderlayLink │ + └────────────┘ └────┬─────┘ │ local/remote: │ + │ │ Device,Interface,│ + │ │ IPAddress │ + ┌────────────┘ └──────────────────┘ + ▼ + ┌──────────────┐ ┌────────────────┐ + │ InfraDevice │◄────────│ InfraPlatform │ + └──────┬───────┘ └────────────────┘ + │ + ┌─────────────┼──────────────┬────────────────┐ + ▼ ▼ ▼ ▼ +┌─────────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────┐ +│InfraInterface│ │InfraBGP- │ │InfraVTEP │ │InfraMlagDomain│ +│ (generic) │ │RouterCfg │ │ │ │ (2 devices) │ +└──────┬──────┘ └────┬─────┘ └─────┬─────┘ └──────┬───────┘ + │ │ │ │ + ▼ ▼ ▼ ▼ + Subtypes: ┌──────────┐ ┌──────────┐ ┌───────────────┐ + - Ethernet │BGPPeer- │ │VlanVni- │ │MlagPeerConfig │ + - Loopback │ Group │ │ Mapping │ │ (per device) │ + - Vlan └──────────┘ └──────────┘ └───────────────┘ + - Lag ┌──────────┐ ┌───────────────┐ + │ │BGPSession│ │MlagInterface │ + ▼ └────┬─────┘ └───────────────┘ +┌──────────────┐ │ +│InfraIPAddress│ │ optional vrf +└──────────────┘ ▼ + ┌─────────┐ ┌──────────────┐ + │InfraVRF │◄────│InfraRoute- │ + └────┬────┘ │ Target │ + │ └──────────────┘ + ▼ + ┌────────────────┐ + │VRFDevice- │ + │ Assignment │ + │ (per device RD)│ + └────────────────┘ - ┌──────────────┐ - │ InfraFabric │ - └──────┬───────┘ - │ - ┌──────────────────────┼──────────────────────┐ - │ │ │ - ▼ ▼ ▼ - ┌────────────┐ ┌─────────────┐ ┌────────────┐ - │ LocationSite│ │ InfraDevice │ │InfraAutono-│ - └────────────┘ │ (spine/ │ │mousSystem │ - │ leaf) │ └─────┬──────┘ - └──────┬──────┘ │ - │ │ - ┌────────────────────────────┼─────────────────────┤ - │ │ │ - ▼ ▼ ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InfraInterface│ │InfraMlagDomain│ │InfraBGPRouter│ -│ (generic) │ │ (leaf pair) │ │ Config │ -└──────┬───────┘ └──────────────┘ └──────┬───────┘ - │ │ - │ ┌─────────────────────────┬───────────────────┤ - │ │ │ │ - ▼ ▼ ▼ ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InterfaceTypes│ │InfraBGPPeer- │ │ InfraBGP- │ -│ - Ethernet │ │ Group │ │ Session │ -│ - Loopback │ │ (underlay, │ │ (neighbors) │ -│ - Vlan │ │ evpn) │ └──────────────┘ -│ - Lag │ └──────────────┘ -└──────┬───────┘ - │ - ▼ -┌──────────────┐ ┌──────────────┐ ┌──────────────┐ -│InfraIPAddress│◄────►│ InfraVLAN │◄────►│ InfraVNI │ -└──────────────┘ └──────────────┘ └──────────────┘ - │ - ▼ - ┌──────────────┐ - │ InfraVTEP │ - └──────────────┘ +Layer 2 / EVPN: +┌──────────┐ ┌──────────┐ ┌──────────────┐ +│InfraVLAN │◄──►│ InfraVNI │ │EVPNInstance │ +│ │ │(L2/L3) │ │(per device │ +│ │ └──────────┘ │ RD/RT) │ +└──────────┘ └──────────────┘ ``` -## Reference Topology Mapping +### Relationship Legend -The schema models this topology from `arista-evpn-vxlan-clab`: +| Symbol | Meaning | +|--------|---------| +| `Parent` → child | Child lifecycle depends on parent (e.g., Device → Interface) | +| `Component` → child | Owned collection (e.g., VTEP → VlanVniMapping) | +| `Attribute` | Association without ownership (e.g., BGPSession → VRF) | +| `Generic` | Polymorphic (e.g., IPAddress → any Interface subtype) | + +### All Relationships + +| Source | Relationship | Target | Kind | Cardinality | +|--------|-------------|--------|------|-------------| +| **base.yml** | | | | | +| InfraInterface | `device` | InfraDevice | Parent | one | +| InfraInterface | `ip_addresses` | InfraIPAddress | Generic | many | +| InfraDevice | `site` | LocationSite | Attribute | one (opt) | +| InfraDevice | `platform` | InfraPlatform | Attribute | one (opt) | +| InfraDevice | `asn` | InfraAutonomousSystem | Attribute | one (opt) | +| InfraDevice | `interfaces` | InfraInterface | Component | many | +| InfraDevice | `mlag_domain` | InfraMlagDomain | Attribute | one (opt) | +| InterfaceEthernet | `lag` | InterfaceLag | Attribute | one (opt) | +| InterfaceEthernet | `connected_interface` | InterfaceEthernet | outbound | one (opt) | +| InterfaceVlan | `vlan` | InfraVLAN | Attribute | one (opt) | +| InterfaceLag | `members` | InterfaceEthernet | Component | many | +| InfraIPAddress | `interface` | InfraInterface | Attribute | one (opt) | +| **bgp.yml** | | | | | +| BGPRouterConfig | `device` | InfraDevice | Parent | one | +| BGPRouterConfig | `local_asn` | InfraAutonomousSystem | Attribute | one | +| BGPRouterConfig | `peer_groups` | BGPPeerGroup | Component | many | +| BGPRouterConfig | `sessions` | BGPSession | Component | many | +| BGPPeerGroup | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPPeerGroup | `remote_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| BGPSession | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPSession | `peer_group` | BGPPeerGroup | Attribute | one (opt) | +| BGPSession | `remote_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| BGPSession | `peer_device` | InfraDevice | Attribute | one (opt) | +| BGPSession | `vrf` | InfraVRF | Attribute | one (opt) | +| BGPAddressFamily | `bgp_config` | BGPRouterConfig | Parent | one | +| BGPAddressFamily | `active_peer_groups` | BGPPeerGroup | Attribute | many | +| BGPAddressFamily | `networks` | InfraIPAddress | Attribute | many (opt) | +| **vlan_vxlan.yml** | | | | | +| InfraVLAN | `vni` | InfraVNI | Attribute | one (opt) | +| InfraVLAN | `site` | LocationSite | Attribute | one (opt) | +| InfraVNI | `vlan` | InfraVLAN | Attribute | one (opt) | +| InfraVNI | `vrf` | InfraVRF | Attribute | one (opt) | +| InfraVTEP | `device` | InfraDevice | Parent | one | +| InfraVTEP | `source_interface` | InterfaceLoopback | Attribute | one | +| InfraVTEP | `vlan_vni_mappings` | VlanVniMapping | Component | many | +| VlanVniMapping | `vtep` | InfraVTEP | Parent | one | +| VlanVniMapping | `vlan` | InfraVLAN | Attribute | one | +| VlanVniMapping | `vni` | InfraVNI | Attribute | one | +| EVPNInstance | `device` | InfraDevice | Parent | one | +| EVPNInstance | `vlan` | InfraVLAN | Attribute | one | +| **vrf.yml** | | | | | +| InfraVRF | `l3vni` | InfraVNI | Attribute | one (opt) | +| InfraVRF | `import_targets` | InfraRouteTarget | outbound | many (opt) | +| InfraVRF | `export_targets` | InfraRouteTarget | outbound | many (opt) | +| InfraVRF | `interfaces` | InfraInterface | Attribute | many (opt) | +| VRFDeviceAssignment | `vrf` | InfraVRF | Attribute | one | +| VRFDeviceAssignment | `device` | InfraDevice | Parent | one | +| VRFDeviceAssignment | `import_targets` | InfraRouteTarget | outbound | many (opt) | +| VRFDeviceAssignment | `export_targets` | InfraRouteTarget | outbound | many (opt) | +| **mlag.yml** | | | | | +| MlagDomain | `devices` | InfraDevice | Attribute | many (2) | +| MlagDomain | `peer_vlan` | InfraVLAN | outbound | one | +| MlagDomain | `ibgp_vlan` | InfraVLAN | outbound | one (opt) | +| MlagPeerConfig | `device` | InfraDevice | Parent | one | +| MlagPeerConfig | `mlag_domain` | MlagDomain | Attribute | one | +| MlagPeerConfig | `local_interface` | InterfaceVlan | Attribute | one | +| MlagPeerConfig | `peer_link` | InterfaceLag | Attribute | one | +| MlagInterface | `mlag_domain` | MlagDomain | Attribute | one | +| MlagInterface | `lag_interfaces` | InterfaceLag | Attribute | many (1-2) | +| **extensions.yml** | | | | | +| InfraFabric | `spine_asn` | InfraAutonomousSystem | Attribute | one (opt) | +| InfraFabric | `sites` | LocationSite | Attribute | many (opt) | +| UnderlayLink | `fabric` | InfraFabric | Parent | one | +| UnderlayLink | `local_device` | InfraDevice | outbound | one | +| UnderlayLink | `local_interface` | InterfaceEthernet | outbound | one | +| UnderlayLink | `local_ip_address` | InfraIPAddress | outbound | one | +| UnderlayLink | `remote_device` | InfraDevice | outbound | one | +| UnderlayLink | `remote_interface` | InterfaceEthernet | outbound | one | +| UnderlayLink | `remote_ip_address` | InfraIPAddress | outbound | one | +| HostConnection | `vlans` | InfraVLAN | Attribute | many | +| HostConnection | `mlag_interface` | MlagInterface | Attribute | one (opt) | +| HostConnection | `lag_interface` | InterfaceLag | Attribute | one (opt) | + +## Reference Topology Mapping | Physical | Infrahub Model | |----------|----------------| @@ -73,22 +164,30 @@ The schema models this topology from `arista-evpn-vxlan-clab`: | leaf1-8 | InfraDevice (role: leaf) | | AS 65000 | InfraAutonomousSystem (spines) | | AS 65001-65004 | InfraAutonomousSystem (leaf pairs) | -| VLAN 40, 34, 78 | InfraVLAN + InfraVNI | -| VLAN 4090, 4091 | InfraVLAN (vlan_type: mlag_peer/mlag_ibgp) | +| AS 64999 | InfraAutonomousSystem (border router) | +| VLAN 40, 34, 78, 900 | InfraVLAN + InfraVNI | +| VLAN 4090, 4091 | InfraVLAN (vlan_type: mlag_peer/mlag_ibgp, trunk_groups, stp_enabled: false) | +| VRF gold | InfraVRF + VRFDeviceAssignment (per-device RD) | +| Route targets 1:100001 | InfraRouteTarget | | leaf1+leaf2 pair | InfraMlagDomain | | Port-Channel999 | InfraInterfaceLag (peer-link) | | Port-Channel1 | InfraMlagInterface (host-facing) | -| Ethernet1-8 | InfraInterfaceEthernet | -| Loopback0, Loopback1 | InfraInterfaceLoopback | +| Ethernet1-12 | InfraInterfaceEthernet | +| Loopback0 | InfraInterfaceLoopback (BGP router-id) | +| Loopback1 | InfraInterfaceLoopback (shared VTEP IP per MLAG pair) | | Vxlan1 | InfraVTEP | -| peer groups | InfraBGPPeerGroup | +| Vlan34/78 SVIs | InfraInterfaceVlan (virtual_router_address for anycast gateway) | +| peer groups (underlay, evpn, underlay_ibgp) | InfraBGPPeerGroup | +| BGP sessions (global) | InfraBGPSession (vrf: null) | +| BGP sessions in VRF gold (leaf7/8 → AS 64999) | InfraBGPSession (vrf: gold) | +| spine1/2 p2p links | InfraUnderlayLink (IPAddress relations, not attributes) | +| distance bgp 20 200 200 | BGPRouterConfig (ebgp_distance, ibgp_distance, local_distance) | ## Usage ### Loading the Schema ```bash -# From the fabric-orchestrator root directory infrahubctl schema load schemas/ ``` @@ -101,12 +200,18 @@ infrahubctl schema check schemas/ ## Key Design Decisions 1. **Generic Interface**: All interface types inherit from `InfraInterface` generic for polymorphic queries -2. **MLAG as Domain**: MLAG is modeled as a domain containing exactly 2 devices, with per-device config +2. **MLAG as Domain**: MLAG is modeled as a domain containing exactly 2 devices, with per-device config via MlagPeerConfig 3. **BGP Hierarchy**: BGPRouterConfig → PeerGroups → Sessions allows template-based configuration -4. **VTEP Independence**: VTEP is separate from Device to support shared VTEP scenarios -5. **EVPN Instance per VLAN**: Allows device-specific RD/RT while referencing common VLAN/VNI +4. **BGP VRF Sessions**: BGPSession has an optional `vrf` relation (kind: Attribute) to support peering inside a VRF context (#50) +5. **VTEP as single model**: VTEP is the unique VXLAN model (InterfaceVxlan was removed to avoid duplication — #44) +6. **EVPN Instance per VLAN**: Allows device-specific RD/RT while referencing common VLAN/VNI +7. **Per-device scoped IDs**: BGPPeerGroup and BGPSession use `bgp_config__router_id__value` prefix in human_friendly_id for global uniqueness (#43) +8. **UnderlayLink IPs as relations**: local/remote IPs reference InfraIPAddress objects instead of inline attributes to avoid dual source of truth (#47) +9. **VRFDeviceAssignment**: Separates VRF definition (global) from per-device assignment (with device-specific RD/RT overrides) +10. **Anycast gateway**: InterfaceVlan has `virtual_router_address` for `ip virtual-router address` and `autostate` for MLAG SVIs (#46) ## Related Issues -- Parent issue: [#41 - Define Infrahub Schema for EVPN-VXLAN Fabric](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues/41) +- Parent issue: [#41 — Define Infrahub Schema for EVPN-VXLAN Fabric](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues/41) +- Schema fixes: #43 (unique IDs), #44 (remove duplicate VTEP), #45 (VLAN unique), #46 (anycast gateway), #47 (underlay IPs), #48 (BGP distance), #49 (trunk groups), #50 (VRF BGP sessions) - Depends on: Schema being loaded before transforms (#30, #31, #32, #33)