Compare commits

..

59 Commits

Author SHA1 Message Date
7fd83b8c3f Merge pull request '[Phase 2] Define Infrahub Schema for EVPN-VXLAN Fabric' (#51) from feature/41-infrahub-schema into main
Reviewed-on: #51
2026-02-13 19:36:26 +00:00
f484af442a docs(schema): update README with complete relationships and topology mapping — refs #41 2026-02-13 14:20:02 +00:00
Damien
e32da46bd7 fix(schema): add optional VRF relation on BGPSession — refs #50 2026-02-13 15:03:55 +01:00
Damien
4e2f5b5b0c Update CLAUDE.md 2026-02-13 15:02:55 +01:00
Damien
cf05a5d477 fix(schema): add trunk_groups and stp_enabled on InfraVLAN — refs #49 2026-02-13 11:25:29 +01:00
Damien
f623d12b8c fix(schema): remove redundant Device.router_id, add BGP distance attributes — refs #48 2026-02-13 11:24:49 +01:00
Damien
e527534820 fix(schema): refactor UnderlayLink IPs from attributes to InfraIPAddress relations — refs #47 2026-02-13 11:24:17 +01:00
Damien
ed820f3380 fix(schema): add virtual_router_address and autostate on InterfaceVlan — refs #46 2026-02-13 11:23:29 +01:00
Damien
82af2daafc fix(schema): add unique constraint on InfraVLAN.vlan_id for human_friendly_id — refs #45 2026-02-13 11:23:02 +01:00
Damien
719ecfafaa fix(schema): remove duplicate InterfaceVxlan, keep VTEP only — refs #44 2026-02-13 11:22:43 +01:00
Damien
3654c2de9d fix(schema): scope BGPPeerGroup and BGPSession human_friendly_id per device — refs #43 2026-02-13 11:21:51 +01:00
Damien
f69bba2bf1 Create CLAUDE.md 2026-02-12 11:19:23 +01:00
aa9d0093fe fix(menu): rename VRF/MLAG namespaces to match Infrahub regex
Infrahub namespaces must match ^[A-Z][a-z0-9]+$
- VRF → Vrf
- MLAG → Mlag
2026-02-09 13:29:11 +00:00
d05c96915f feat(schema): add include_in_menu: false to all extension nodes #41 2026-02-09 12:05:11 +00:00
e31846b057 feat(schema): add include_in_menu: false to all MLAG nodes #41 2026-02-09 12:04:46 +00:00
741132a176 feat(schema): add include_in_menu: false to all VRF nodes #41 2026-02-09 12:04:21 +00:00
a05e997742 feat(schema): add include_in_menu: false to all VLAN/VXLAN nodes #41 2026-02-09 12:04:04 +00:00
ffa1eff19a feat(schema): add include_in_menu: false to all BGP nodes #41 2026-02-09 12:03:38 +00:00
69f003b798 feat(schema): add include_in_menu: false to all base nodes #41
Menu is now controlled by custom menus/fabric-menu.yml
2026-02-09 12:03:09 +00:00
40fdf504c9 feat(config): add menu reference to .infrahub.yml #41 2026-02-09 12:02:29 +00:00
78263e8bf5 feat(menu): add custom Infrahub menu for EVPN-VXLAN fabric #41
Organize 22+ schema nodes into logical categories:
- Fabric Topology (Fabric, Site, Device, Platform, Underlay Links)
- Interfaces (Ethernet, Loopback, VLAN SVI, LAG, VXLAN)
- IP Addressing
- Layer 2 / VXLAN (VLAN, VNI, VTEP, Mappings, EVPN)
- Routing / BGP (AS, Router Config, Peer Groups, Sessions, AFI)
- VRF (VRF, Route Targets, Assignments)
- MLAG (Domain, Peer Config, Interface)
- Host Connectivity
2026-02-09 12:02:18 +00:00
25550bb3c4 fix: migrate display_labels to display_label Jinja2 format in VRF schema
Also enriched VRFDeviceAssignment display_label to show device + VRF.

Refs #41
2026-02-07 09:18:38 +00:00
b9b15f3beb fix: migrate display_labels to display_label Jinja2 format in VLAN/VXLAN schema
Refs #41
2026-02-07 09:18:11 +00:00
d9b47461d3 fix: migrate display_labels to display_label Jinja2 format in MLAG schema
Refs #41
2026-02-07 09:17:46 +00:00
498fa8505e fix: migrate display_labels to display_label Jinja2 format in extensions schema
Refs #41
2026-02-07 09:17:26 +00:00
cda3804c2c fix: migrate display_labels to display_label Jinja2 format in BGP schema
Refs #41
2026-02-07 09:17:07 +00:00
97080473f7 fix: migrate display_labels to display_label Jinja2 format in base schema
Replaces deprecated display_labels list format and bare display_label
strings with the new Jinja2 template format as required by Infrahub.

Refs #41
2026-02-07 09:16:40 +00:00
bb76b93499 refactor(schema): replace deprecated display_labels with display_label 2026-02-07 09:03:36 +00:00
a917715a47 refactor(schema): replace deprecated display_labels with display_label across all nodes 2026-02-07 09:03:11 +00:00
99f34b9639 fix(schema): add unique: true on VRF.name for HFID peer traversal 2026-02-06 19:39:28 +00:00
0e96e8aca8 fix(schema): add explicit optional: false on VRFDeviceAssignment.vrf for human_friendly_id 2026-02-06 19:20:56 +00:00
d7e2d9f0e0 fix(schema): add optional: false on UnderlayLink.fabric parent relationship 2026-02-06 19:19:55 +00:00
0c0ab1b214 fix(schema): add explicit optional: false to Parent relationships in vrf.yml 2026-02-06 15:10:16 +00:00
a12e24d00c fix(schema): add explicit optional: false to all Parent relationships in vlan_vxlan.yml 2026-02-06 15:10:00 +00:00
67a54e349d fix(schema): add explicit optional: false to Parent relationships in mlag.yml 2026-02-06 15:09:25 +00:00
adb02fc25c fix(schema): add explicit optional: false to all Parent relationships in bgp.yml 2026-02-06 15:08:57 +00:00
ef6877551f fix(schema): IPAddress.interface - replace Parent with Attribute kind
Parent relationships cannot be optional in Infrahub. Since an IP address
can exist without being assigned to an interface (reserved, planned),
we use kind: Attribute instead of kind: Parent.

Also change InfraInterface.ip_addresses from Component to Generic
since Component requires a matching Parent on the other side.

Both sides now use explicit identifier: interface__ip_addresses
for proper bidirectional linking.
2026-02-06 15:07:01 +00:00
4aadf763a3 fix(schema): add optional: false on device relationship for uniqueness_constraints 2026-02-06 13:11:52 +00:00
52c335aeb0 fix(schema): display_labels must only reference local attributes in vrf.yml 2026-02-06 13:08:59 +00:00
2ca08a4f41 fix(schema): display_labels must only reference local attributes in vlan_vxlan.yml 2026-02-06 13:08:30 +00:00
95bd2ee6c8 fix(schema): display_labels must only reference local attributes in mlag.yml 2026-02-06 13:08:04 +00:00
42d03699d9 fix(schema): display_labels must only reference local attributes in extensions.yml 2026-02-06 13:07:44 +00:00
c22a5b6ab4 fix(schema): display_labels must only reference attributes, not relationships 2026-02-06 13:07:24 +00:00
4e9c2d3009 fix(schema): replace deprecated default_filter with human_friendly_id in base.yml 2026-02-06 13:06:58 +00:00
eb809812af fix(schema): add direction outbound for self-referencing relationship
InterfaceEthernet.connected_interface is a self-reference that requires
direction: outbound to avoid bidirectional conflicts per Infrahub docs.

Ref: #41
2026-02-06 09:12:15 +00:00
8114b6d973 fix(schema): add unique identifiers for VRF RouteTarget relationships
Add identifier and direction: outbound for import/export targets
in VRF and VRFDeviceAssignment to avoid bidirectional conflicts.

Ref: #41
2026-02-06 09:09:31 +00:00
6d08b19b5f fix(schema): add unique identifiers for MlagDomain VLAN relationships
Add identifier and direction: outbound for peer_vlan and ibgp_vlan
to avoid bidirectional relationship conflicts.

Ref: #41
2026-02-06 09:04:39 +00:00
4f5fef7203 fix(schema): use direction outbound for UnderlayLink relationships
Use outbound direction to avoid bidirectional relationship conflicts
when multiple relationships point to the same peer type.

Ref: #41
2026-02-06 08:55:08 +00:00
afa268ad2d fix(schema): add unique identifiers for UnderlayLink relationships
Infrahub requires unique identifiers when multiple relationships
point to the same peer type with the same direction.

Ref: #41
2026-02-06 08:51:47 +00:00
c2a92c340d fix(schema): rename rd to route_distinguisher in EVPNInstance
Infrahub requires attribute names to have at least 3 characters.

Ref: #41
2026-02-06 08:29:12 +00:00
443642c2a1 fix(schema): rename rd to route_distinguisher (min 3 chars)
Infrahub requires attribute names to have at least 3 characters.

Ref: #41
2026-02-06 08:28:42 +00:00
Damien
ea6b66d639 docs: reformat README tables for better raw readability
Update Markdown tables including InfraHub comparison, Prefect benefits, and project progress phases to use consistent column padding. This improves the visual alignment and readability when viewing the raw source file.
2026-02-06 09:00:27 +01:00
f03698dec5 docs(schema): add schema documentation and ERD
Document all schema files, entity relationships, and mapping
to the reference arista-evpn-vxlan-clab topology.

Ref: #41
2026-02-05 15:54:38 +00:00
bd46d5f046 feat(schema): add extensions schema
Add Fabric, Underlay Link, and Host Connection models
for fabric-wide configuration and topology documentation.

Ref: #41
2026-02-05 15:54:07 +00:00
e3ef0b3763 feat(schema): add MLAG schema
Add models for MLAG Domain, Peer Config, and MLAG Interfaces.
Supports dual-primary detection and heartbeat configuration.

Ref: #41
2026-02-05 15:53:49 +00:00
3e96b0ff1a feat(schema): add BGP schema
Add models for Autonomous System, BGP Router Config, Peer Groups,
BGP Sessions, and Address Families. Supports underlay and EVPN overlay.

Ref: #41
2026-02-05 15:53:32 +00:00
d87ffcaca6 feat(schema): add VRF schema
Add models for VRF, Route Target, and VRF-Device assignments.
Supports L3VNI association for symmetric IRB routing.

Ref: #41
2026-02-05 15:53:11 +00:00
535f24a920 feat(schema): add VLAN and VXLAN schema
Add models for VLAN, VNI, VTEP, VLAN-VNI mappings, and EVPN instances.
Supports L2VNI and L3VNI types for EVPN-VXLAN fabric.

Ref: #41
2026-02-05 15:52:58 +00:00
077917f011 feat(schema): add base infrastructure schema
Add core infrastructure models for Device, Interface, IPAddress,
and Platform based on the arista-evpn-vxlan-clab topology.

Ref: #41
2026-02-05 15:52:36 +00:00
11 changed files with 1855 additions and 34 deletions

7
.infrahub.yml Normal file
View File

@@ -0,0 +1,7 @@
# yaml-language-server: $schema=https://schema.infrahub.app/python-sdk/repository-config/latest.json
---
schemas:
- schemas/
menus:
- menus/fabric-menu.yml

82
CLAUDE.md Normal file
View File

@@ -0,0 +1,82 @@
# Claude Code Instructions — fabric-orchestrator
## Project Context
Fabric-orchestrator manages Arista EVPN-VXLAN fabrics using Infrahub as the source of truth.
Gitea: https://gitea.arnodo.fr/Damien/fabric-orchestrator
Branch: `feature/41-infrahub-schema`
## Reference Topology (overlaid.net)
- 2 spines (AS 65000), 8 leafs in 4 MLAG pairs (AS 6500165004)
- Loopback0: BGP router-id per device, Loopback1: shared VTEP IP per MLAG pair
- VLANs 4090 (MLAG peer) / 4091 (MLAG iBGP) with trunk groups
- Underlay: eBGP point-to-point (spine↔leaf) + iBGP (leaf↔leaf peer)
- Overlay: EVPN eBGP multihop on loopbacks, spines as route-reflectors with next-hop-unchanged
- L2VXLAN (EVPN Type-2): VLAN→VNI mapping, redistribute learned
- L3VXLAN (EVPN Type-5): VRF→VNI mapping, redistribute connected
- Border peering: BGP sessions inside VRF (leaf7/8 → AS 64999 in VRF gold)
## Schema Files (Infrahub YAML format, in `schemas/`)
| File | Content |
| ---------------- | ----------------------------------------------------------------------------- |
| `base.yml` | Device, Interfaces (Ethernet, Loopback, Vlan, Lag, Vxlan), IPAddress |
| `bgp.yml` | AutonomousSystem, BGPRouterConfig, BGPPeerGroup, BGPSession, BGPAddressFamily |
| `vlan_vxlan.yml` | VLAN, VNI, VTEP, VlanVniMapping, EVPNInstance |
| `vrf.yml` | VRFConfig, RouteTarget, VRFDeviceAssignment |
| `mlag.yml` | MlagDomain, MlagPeerConfig, MlagInterface |
| `extensions.yml` | UnderlayLink, HostConnection, FabricSettings |
## Infrahub Schema Rules
1. `human_friendly_id` fields MUST have `unique: true` — globally unique across all instances
2. To scope human_friendly_id per-device, traverse Parent relationships:
`parent_rel__parent_attr__value` (e.g. `device__name__value`)
3. Parent relationships (`kind: Parent`) need `optional: false` explicitly
4. Self-referencing relationships need `direction: outbound`
5. Multiple relationships to the same peer type need distinct `identifier` values
6. Don't model the same concept twice (e.g. VTEP source_address vs InterfaceVxlan source_interface)
7. `kind: Attribute` for association, `kind: Component` for ownership (lifecycle-coupled)
8. `kind: Parent` implies the child cannot exist without the parent
## Validation
```bash
infrahubctl schema check schemas/
```
Always run before committing. Fix any errors before pushing.
## Commit Convention
```
fix(schema): short description — refs #<issue>
feat(schema): short description — refs #<issue>
```
- One logical change per commit
- Reference the Gitea issue number
- Comment on the issue after implementation with changes summary
## Open Issues (prioritized)
Check https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues for current backlog.
Critical issues (blocking data load) take priority over functional improvements.
Dependency chain: resolve critical → significant → minor sequentially.
## Workflow
1. Read the issue description fully before starting
2. Read relevant schema files to understand current state
3. Make minimal, targeted changes
4. Validate with `infrahubctl schema check schemas/`
5. Commit with proper message referencing the issue
6. Comment on the Gitea issue with what was changed
## Don'ts
- Don't add fields not needed by the reference topology
- Don't change `human_friendly_id` without checking uniqueness implications
- Don't remove existing relationships without checking reverse dependencies
- Don't create new schema files without discussing first

View File

@@ -24,14 +24,14 @@ Think `terraform plan` and `terraform apply`, but for your network fabric — po
We chose [InfraHub](https://github.com/opsmill/infrahub) over NetBox as Source of Truth for several reasons:
| Feature | NetBox | InfraHub |
|---------|--------|----------|
| **Schema** | Fixed DCIM/IPAM model | Fully customizable YAML schema |
| **Git Integration** | External sync needed | Native - branches = data branches |
| **Versioning** | Changelog only | True Git-like versioning with merges |
| **Test/Redeploy** | Dump/restore | `git clone` = complete environment |
| **Transforms** | Limited | Built-in Jinja2 + Python transforms |
| **GraphQL** | Yes | Yes (auto-generated from schema) |
| Feature | NetBox | InfraHub |
| ------------------- | --------------------- | ------------------------------------ |
| **Schema** | Fixed DCIM/IPAM model | Fully customizable YAML schema |
| **Git Integration** | External sync needed | Native - branches = data branches |
| **Versioning** | Changelog only | True Git-like versioning with merges |
| **Test/Redeploy** | Dump/restore | `git clone` = complete environment |
| **Transforms** | Limited | Built-in Jinja2 + Python transforms |
| **GraphQL** | Yes | Yes (auto-generated from schema) |
**Key benefits for this project:**
@@ -98,16 +98,16 @@ git push
## 🎛 Why Prefect?
| Feature | Benefit |
|---------|---------|
| **Python-native workflows** | Use `@flow` and `@task` decorators — no YAML, just Python |
| **Free secrets management** | Native `Secret` blocks for credentials (free in OSS) |
| **Built-in UI** | Dashboard, logs, metrics, execution history via `prefect server start` |
| **No containerization required** | Run flows directly with `.serve()` — no Docker needed |
| **Event-driven triggers** | Schedule, webhooks (via FastAPI), flow triggers out of the box |
| **Task dependencies** | Automatic dependency ordering via task result passing or `wait_for` |
| **Retry & error handling** | Built-in retry policies with `@task(retries=3)` |
| **Human-in-the-loop** | Native `pause_flow_run()` for approval workflows |
| Feature | Benefit |
| -------------------------------- | ---------------------------------------------------------------------- |
| **Python-native workflows** | Use `@flow` and `@task` decorators — no YAML, just Python |
| **Free secrets management** | Native `Secret` blocks for credentials (free in OSS) |
| **Built-in UI** | Dashboard, logs, metrics, execution history via `prefect server start` |
| **No containerization required** | Run flows directly with `.serve()` — no Docker needed |
| **Event-driven triggers** | Schedule, webhooks (via FastAPI), flow triggers out of the box |
| **Task dependencies** | Automatic dependency ordering via task result passing or `wait_for` |
| **Retry & error handling** | Built-in retry policies with `@task(retries=3)` |
| **Human-in-the-loop** | Native `pause_flow_run()` for approval workflows |
## 🎯 Target Fabric
@@ -124,12 +124,12 @@ Reference: [arista-evpn-vxlan-clab](https://gitea.arnodo.fr/Damien/arista-evpn-v
Progress is tracked via issues. See [all issues](https://gitea.arnodo.fr/Damien/fabric-orchestrator/issues) or filter by phase:
| Phase | Description | Status |
|-------|-------------|--------|
| **Phase 1** | YANG Path Discovery - Map EOS 4.35.0F YANG models, validate gNMI | ✅ Complete |
| Phase | Description | Status |
| ----------- | -------------------------------------------------------------------- | ------------- |
| **Phase 1** | YANG Path Discovery - Map EOS 4.35.0F YANG models, validate gNMI | ✅ Complete |
| **Phase 2** | InfraHub Setup & Core Reconciler - Schema, diff engine, YANG mappers | 🔄 In Progress |
| **Phase 3** | Full Fabric Coverage - BGP, MLAG, VRFs mappers | 📋 Planned |
| **Phase 4** | Prefect Integration - Flows, webhooks, drift detection | 📋 Planned |
| **Phase 3** | Full Fabric Coverage - BGP, MLAG, VRFs mappers | 📋 Planned |
| **Phase 4** | Prefect Integration - Flows, webhooks, drift detection | 📋 Planned |
## 📁 Project Structure
@@ -197,17 +197,17 @@ fabric-orchestrator/
## 🛠️ Technology Stack
| Component | Technology | Purpose |
|-----------|------------|---------|
| Source of Truth | **InfraHub** | Intent definition via custom schema |
| Data Storage | **This Git repo** | Schema + data versioned together |
| Orchestrator | **Prefect** | Python-native workflow orchestration |
| Transport | gNMI | Configuration and telemetry |
| Data Models | YANG (OpenConfig + Arista) | Structured configuration |
| Python Library | pygnmi + infrahub-sdk | gNMI/InfraHub interactions |
| CLI | Click + Rich | YANG discovery tools |
| Validation | Pydantic v2 | Intent data validation |
| Lab | ContainerLab + cEOS | Development environment |
| Component | Technology | Purpose |
| --------------- | -------------------------- | ------------------------------------ |
| Source of Truth | **InfraHub** | Intent definition via custom schema |
| Data Storage | **This Git repo** | Schema + data versioned together |
| Orchestrator | **Prefect** | Python-native workflow orchestration |
| Transport | gNMI | Configuration and telemetry |
| Data Models | YANG (OpenConfig + Arista) | Structured configuration |
| Python Library | pygnmi + infrahub-sdk | gNMI/InfraHub interactions |
| CLI | Click + Rich | YANG discovery tools |
| Validation | Pydantic v2 | Intent data validation |
| Lab | ContainerLab + cEOS | Development environment |
## 🔗 Related Projects

247
menus/fabric-menu.yml Normal file
View File

@@ -0,0 +1,247 @@
# yaml-language-server: $schema=https://schema.infrahub.app/infrahub/menu/latest.json
# Custom menu for EVPN-VXLAN Fabric Orchestrator
# Organizes schema nodes into logical topology-aligned categories
---
apiversion: infrahub.app/v1
kind: Menu
spec:
data:
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Fabric Topology
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Topology
name: Mainmenu
label: Fabric Topology
icon: "mdi:lan"
children:
data:
- namespace: Topology
name: Fabric
label: Fabrics
kind: InfraFabric
icon: "mdi:vector-polygon"
- namespace: Topology
name: Site
label: Sites
kind: LocationSite
icon: "mingcute:building-4-line"
- namespace: Topology
name: Device
label: Devices
kind: InfraDevice
icon: "mdi:server-network"
- namespace: Topology
name: Platform
label: Platforms
kind: InfraPlatform
icon: "mdi:chip"
- namespace: Topology
name: UnderlayLink
label: Underlay Links
kind: InfraUnderlayLink
icon: "mdi:cable-data"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Interfaces
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Interfaces
name: Mainmenu
label: Interfaces
icon: "mdi:ethernet"
children:
data:
- namespace: Interfaces
name: Ethernet
label: Ethernet
kind: InfraInterfaceEthernet
icon: "mdi:ethernet"
- namespace: Interfaces
name: Loopback
label: Loopback
kind: InfraInterfaceLoopback
icon: "mdi:reload"
- namespace: Interfaces
name: VlanSvi
label: VLAN SVI
kind: InfraInterfaceVlan
icon: "mdi:lan"
- namespace: Interfaces
name: Lag
label: LAG / Port-Channel
kind: InfraInterfaceLag
icon: "mdi:link-variant"
- namespace: Interfaces
name: Vxlan
label: VXLAN Tunnel
kind: InfraInterfaceVxlan
icon: "mdi:tunnel"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# IP Addressing
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Addressing
name: Mainmenu
label: IP Addressing
icon: "mdi:ip-network"
children:
data:
- namespace: Addressing
name: IPAddress
label: IP Addresses
kind: InfraIPAddress
icon: "mdi:ip-network"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Layer 2 / VXLAN
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Layer2
name: Mainmenu
label: Layer 2 / VXLAN
icon: "mdi:switch"
children:
data:
- namespace: Layer2
name: Vlan
label: VLANs
kind: InfraVLAN
icon: "mdi:lan-connect"
- namespace: Layer2
name: Vni
label: VNIs
kind: InfraVNI
icon: "mdi:tunnel-outline"
- namespace: Layer2
name: Vtep
label: VTEPs
kind: InfraVTEP
icon: "mdi:server-network-outline"
- namespace: Layer2
name: VlanVniMapping
label: VLAN-VNI Mappings
kind: InfraVlanVniMapping
icon: "mdi:swap-horizontal"
- namespace: Layer2
name: EvpnInstance
label: EVPN Instances
kind: InfraEVPNInstance
icon: "mdi:cloud-sync"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Routing / BGP
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Routing
name: Mainmenu
label: Routing / BGP
icon: "mdi:routes"
children:
data:
- namespace: Routing
name: AutonomousSystem
label: Autonomous Systems
kind: InfraAutonomousSystem
icon: "mdi:cloud-outline"
- namespace: Routing
name: BGPRouterConfig
label: BGP Router Config
kind: InfraBGPRouterConfig
icon: "mdi:router-wireless"
- namespace: Routing
name: BGPPeerGroup
label: BGP Peer Groups
kind: InfraBGPPeerGroup
icon: "mdi:account-group"
- namespace: Routing
name: BGPSession
label: BGP Sessions
kind: InfraBGPSession
icon: "mdi:connection"
- namespace: Routing
name: BGPAddressFamily
label: BGP Address Families
kind: InfraBGPAddressFamily
icon: "mdi:format-list-bulleted"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# VRF
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Vrf
name: Mainmenu
label: VRF
icon: "mdi:router"
children:
data:
- namespace: Vrf
name: Vrf
label: VRFs
kind: InfraVRF
icon: "mdi:router"
- namespace: Vrf
name: RouteTarget
label: Route Targets
kind: InfraRouteTarget
icon: "mdi:target"
- namespace: Vrf
name: VrfAssignment
label: VRF Assignments
kind: InfraVRFDeviceAssignment
icon: "mdi:router-network"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# MLAG
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Mlag
name: Mainmenu
label: MLAG
icon: "mdi:link-variant"
children:
data:
- namespace: Mlag
name: MlagDomain
label: MLAG Domains
kind: InfraMlagDomain
icon: "mdi:link-variant"
- namespace: Mlag
name: MlagPeerConfig
label: MLAG Peer Config
kind: InfraMlagPeerConfig
icon: "mdi:server-network"
- namespace: Mlag
name: MlagInterface
label: MLAG Interfaces
kind: InfraMlagInterface
icon: "mdi:ethernet-cable"
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Host Connectivity
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- namespace: Connectivity
name: Mainmenu
label: Host Connectivity
icon: "mdi:desktop-tower"
children:
data:
- namespace: Connectivity
name: HostConnection
label: Host Connections
kind: InfraHostConnection
icon: "mdi:desktop-tower"

217
schemas/README.md Normal file
View File

@@ -0,0 +1,217 @@
# 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 [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 | 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
```
┌──────────────┐
│ 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)│
└────────────────┘
Layer 2 / EVPN:
┌──────────┐ ┌──────────┐ ┌──────────────┐
│InfraVLAN │◄──►│ InfraVNI │ │EVPNInstance │
│ │ │(L2/L3) │ │(per device │
│ │ └──────────┘ │ RD/RT) │
└──────────┘ └──────────────┘
```
### Relationship Legend
| 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 |
|----------|----------------|
| spine1, spine2 | InfraDevice (role: spine) |
| leaf1-8 | InfraDevice (role: leaf) |
| AS 65000 | InfraAutonomousSystem (spines) |
| AS 65001-65004 | InfraAutonomousSystem (leaf pairs) |
| 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-12 | InfraInterfaceEthernet |
| Loopback0 | InfraInterfaceLoopback (BGP router-id) |
| Loopback1 | InfraInterfaceLoopback (shared VTEP IP per MLAG pair) |
| Vxlan1 | InfraVTEP |
| 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
infrahubctl schema load schemas/
```
### Validation
```bash
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 via MlagPeerConfig
3. **BGP Hierarchy**: BGPRouterConfig → PeerGroups → Sessions allows template-based configuration
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)
- 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)

347
schemas/base.yml Normal file
View File

@@ -0,0 +1,347 @@
# Base Infrastructure Schema for EVPN-VXLAN Fabric
# This schema defines core infrastructure objects required for fabric orchestration
---
version: "1.0"
generics:
- name: Interface
namespace: Infra
description: Generic interface - parent for all interface types
label: Interface
include_in_menu: false
hierarchical: false
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
description: Interface name (e.g., Ethernet1, Loopback0)
- name: description
kind: Text
optional: true
- name: enabled
kind: Boolean
default_value: true
- name: mtu
kind: Number
optional: true
description: Maximum Transmission Unit
relationships:
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false
- name: ip_addresses
peer: InfraIPAddress
identifier: interface__ip_addresses
cardinality: many
kind: Generic
nodes:
# ================================================================
# Location
# ================================================================
- name: Site
namespace: Location
description: Physical site or data center
label: Site
icon: mingcute--building-4-line
include_in_menu: false
human_friendly_id:
- name__value
order_by:
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
unique: true
- name: description
kind: Text
optional: true
- name: facility
kind: Text
optional: true
description: Facility identifier or code
# ================================================================
# Platform
# ================================================================
- name: Platform
namespace: Infra
description: Device platform/OS (e.g., Arista EOS, Cisco NX-OS)
label: Platform
icon: mdi--chip
include_in_menu: false
human_friendly_id:
- name__value
order_by:
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
unique: true
description: Platform name (e.g., arista_eos, cisco_nxos)
- name: description
kind: Text
optional: true
- name: napalm_driver
kind: Text
optional: true
description: NAPALM driver name
- name: netmiko_device_type
kind: Text
optional: true
description: Netmiko device type
# ================================================================
# Device
# ================================================================
- name: Device
namespace: Infra
description: Network device (spine, leaf, etc.)
label: Device
icon: mdi--server-network
include_in_menu: false
human_friendly_id:
- name__value
order_by:
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
unique: true
description: Device hostname
- name: description
kind: Text
optional: true
- name: role
kind: Dropdown
choices:
- name: spine
label: Spine
color: "#3b82f6"
- name: leaf
label: Leaf
color: "#22c55e"
- name: border_leaf
label: Border Leaf
color: "#f59e0b"
description: Fabric role
- name: status
kind: Dropdown
default_value: active
choices:
- name: active
label: Active
color: "#22c55e"
- name: planned
label: Planned
color: "#3b82f6"
- name: maintenance
label: Maintenance
color: "#f59e0b"
- name: decommissioned
label: Decommissioned
color: "#ef4444"
relationships:
- name: site
peer: LocationSite
cardinality: one
optional: true
- name: platform
peer: InfraPlatform
cardinality: one
optional: true
- name: asn
peer: InfraAutonomousSystem
cardinality: one
optional: true
description: BGP Autonomous System
- name: interfaces
peer: InfraInterface
cardinality: many
kind: Component
- name: mlag_domain
peer: InfraMlagDomain
cardinality: one
optional: true
# ================================================================
# Interface Types (inherit from InfraInterface generic)
# ================================================================
- name: InterfaceEthernet
namespace: Infra
description: Physical Ethernet interface
label: Ethernet Interface
icon: mdi--ethernet
include_in_menu: false
inherit_from:
- InfraInterface
uniqueness_constraints:
- ["device", "name__value"]
human_friendly_id:
- device__name__value
- name__value
display_label: "{{ name__value }}"
attributes:
- name: speed
kind: Dropdown
optional: true
choices:
- name: "1000"
label: 1 Gbps
- name: "10000"
label: 10 Gbps
- name: "25000"
label: 25 Gbps
- name: "40000"
label: 40 Gbps
- name: "100000"
label: 100 Gbps
- name: mode
kind: Dropdown
optional: true
choices:
- name: access
label: Access
- name: trunk
label: Trunk
- name: routed
label: Routed (L3)
description: Switchport mode
relationships:
- name: lag
peer: InfraInterfaceLag
cardinality: one
optional: true
description: Parent LAG interface
- name: connected_interface
peer: InfraInterfaceEthernet
identifier: ethernet_connected_to
direction: outbound
cardinality: one
optional: true
description: Connected peer interface
- name: InterfaceLoopback
namespace: Infra
description: Loopback interface
label: Loopback Interface
icon: mdi--reload
include_in_menu: false
inherit_from:
- InfraInterface
uniqueness_constraints:
- ["device", "name__value"]
human_friendly_id:
- device__name__value
- name__value
display_label: "{{ name__value }}"
- name: InterfaceVlan
namespace: Infra
description: VLAN SVI interface
label: VLAN Interface
icon: mdi--lan
include_in_menu: false
inherit_from:
- InfraInterface
uniqueness_constraints:
- ["device", "name__value"]
human_friendly_id:
- device__name__value
- name__value
display_label: "{{ name__value }}"
attributes:
- name: virtual_router_address
kind: IPHost
optional: true
description: Anycast gateway IP (ip virtual-router address)
- name: autostate
kind: Boolean
default_value: true
description: "Enable autostate (set false for MLAG peer SVIs)"
relationships:
- name: vlan
peer: InfraVLAN
cardinality: one
optional: true
- name: InterfaceLag
namespace: Infra
description: Link Aggregation (Port-Channel) interface
label: LAG Interface
icon: mdi--link-variant
include_in_menu: false
inherit_from:
- InfraInterface
uniqueness_constraints:
- ["device", "name__value"]
human_friendly_id:
- device__name__value
- name__value
display_label: "{{ name__value }}"
attributes:
- name: lacp_mode
kind: Dropdown
optional: true
choices:
- name: active
label: Active
- name: passive
label: Passive
- name: static
label: Static (No LACP)
- name: mlag_id
kind: Number
optional: true
description: MLAG interface ID
relationships:
- name: members
peer: InfraInterfaceEthernet
cardinality: many
kind: Component
# ================================================================
# IP Address
# ================================================================
- name: IPAddress
namespace: Infra
description: IP Address assignment
label: IP Address
icon: mdi--ip-network
include_in_menu: false
human_friendly_id:
- address__value
order_by:
- address__value
display_label: "{{ address__value }}"
attributes:
- name: address
kind: IPNetwork
description: IP address with prefix (e.g., 10.0.1.1/31)
- name: description
kind: Text
optional: true
- name: status
kind: Dropdown
default_value: active
choices:
- name: active
label: Active
color: "#22c55e"
- name: reserved
label: Reserved
color: "#3b82f6"
- name: deprecated
label: Deprecated
color: "#ef4444"
relationships:
- name: interface
peer: InfraInterface
identifier: interface__ip_addresses
cardinality: one
optional: true
kind: Attribute

271
schemas/bgp.yml Normal file
View File

@@ -0,0 +1,271 @@
# BGP Schema for EVPN-VXLAN Fabric
# Defines Autonomous System, Peer Groups, and BGP Sessions
---
version: "1.0"
nodes:
# ================================================================
# Autonomous System
# ================================================================
- name: AutonomousSystem
namespace: Infra
description: BGP Autonomous System
label: Autonomous System
icon: mdi--cloud-outline
include_in_menu: false
human_friendly_id:
- asn__value
order_by:
- asn__value
display_label: "{{ asn__value }}"
attributes:
- name: asn
kind: Number
unique: true
description: AS Number (e.g., 65000)
- name: description
kind: Text
optional: true
- name: as_type
kind: Dropdown
default_value: private
choices:
- name: private
label: Private
- name: public
label: Public
# ================================================================
# BGP Router Configuration (per device)
# ================================================================
- name: BGPRouterConfig
namespace: Infra
description: BGP router configuration on a device
label: BGP Router Config
icon: mdi--router-wireless
include_in_menu: false
human_friendly_id:
- device__name__value
display_label: "{{ router_id__value }}"
attributes:
- name: router_id
kind: IPHost
unique: true
description: BGP Router ID
- name: default_ipv4_unicast
kind: Boolean
default_value: false
description: Enable default IPv4 unicast
- name: log_neighbor_changes
kind: Boolean
default_value: true
- name: ecmp_max_paths
kind: Number
default_value: 4
description: Maximum ECMP paths
- name: ecmp_max_ecmp
kind: Number
default_value: 64
description: Maximum ECMP routes
- name: ebgp_distance
kind: Number
default_value: 20
description: eBGP administrative distance
- name: ibgp_distance
kind: Number
default_value: 200
description: iBGP administrative distance
- name: local_distance
kind: Number
default_value: 200
description: Local route administrative distance
relationships:
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false
- name: local_asn
peer: InfraAutonomousSystem
cardinality: one
- name: peer_groups
peer: InfraBGPPeerGroup
cardinality: many
kind: Component
- name: sessions
peer: InfraBGPSession
cardinality: many
kind: Component
# ================================================================
# BGP Peer Group
# ================================================================
- name: BGPPeerGroup
namespace: Infra
description: BGP peer group template
label: BGP Peer Group
icon: mdi--account-group
include_in_menu: false
uniqueness_constraints:
- ["bgp_config", "name__value"]
human_friendly_id:
- bgp_config__router_id__value
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
description: Peer group name (e.g., underlay, evpn)
- name: description
kind: Text
optional: true
- name: update_source
kind: Text
optional: true
description: Update source interface (e.g., Loopback0)
- name: ebgp_multihop
kind: Number
optional: true
description: eBGP multihop TTL
- name: send_community
kind: Dropdown
default_value: none
choices:
- name: none
label: None
- name: standard
label: Standard
- name: extended
label: Extended
- name: both
label: Both
- name: next_hop_self
kind: Boolean
default_value: false
- name: next_hop_unchanged
kind: Boolean
default_value: false
description: Keep next-hop unchanged (for route reflector)
- name: maximum_routes
kind: Number
optional: true
- name: maximum_routes_warning_only
kind: Boolean
default_value: true
- name: peer_group_type
kind: Dropdown
default_value: underlay
choices:
- name: underlay
label: Underlay IPv4
- name: underlay_ibgp
label: Underlay iBGP
- name: evpn
label: EVPN Overlay
relationships:
- name: bgp_config
peer: InfraBGPRouterConfig
cardinality: one
kind: Parent
optional: false
- name: remote_asn
peer: InfraAutonomousSystem
cardinality: one
optional: true
# ================================================================
# BGP Session (Neighbor)
# ================================================================
- name: BGPSession
namespace: Infra
description: BGP neighbor session
label: BGP Session
icon: mdi--connection
include_in_menu: false
uniqueness_constraints:
- ["bgp_config", "peer_address__value"]
human_friendly_id:
- bgp_config__router_id__value
- peer_address__value
display_label: "{{ peer_address__value }}"
attributes:
- name: peer_address
kind: IPHost
description: Neighbor IP address
- name: description
kind: Text
optional: true
- name: enabled
kind: Boolean
default_value: true
relationships:
- name: bgp_config
peer: InfraBGPRouterConfig
cardinality: one
kind: Parent
optional: false
- name: peer_group
peer: InfraBGPPeerGroup
cardinality: one
optional: true
- name: remote_asn
peer: InfraAutonomousSystem
cardinality: one
optional: true
description: Override peer group remote-as
- name: peer_device
peer: InfraDevice
cardinality: one
optional: true
description: Remote peer device (for documentation)
- name: vrf
peer: InfraVRF
cardinality: one
kind: Attribute
optional: true
description: VRF context for this session (null = global BGP process)
# ================================================================
# BGP Address Family Configuration
# ================================================================
- name: BGPAddressFamily
namespace: Infra
description: BGP address family configuration
label: BGP Address Family
icon: mdi--format-list-bulleted
include_in_menu: false
display_label: "{{ afi__value }}"
attributes:
- name: afi
kind: Dropdown
choices:
- name: ipv4
label: IPv4
- name: ipv6
label: IPv6
- name: evpn
label: EVPN
description: Address Family Identifier
- name: safi
kind: Dropdown
default_value: unicast
choices:
- name: unicast
label: Unicast
- name: multicast
label: Multicast
description: Sub Address Family Identifier
relationships:
- name: bgp_config
peer: InfraBGPRouterConfig
cardinality: one
kind: Parent
optional: false
- name: active_peer_groups
peer: InfraBGPPeerGroup
cardinality: many
description: Peer groups activated in this AF
- name: networks
peer: InfraIPAddress
cardinality: many
optional: true
description: Networks to advertise

164
schemas/extensions.yml Normal file
View File

@@ -0,0 +1,164 @@
# Extensions Schema for EVPN-VXLAN Fabric
# Custom attributes and fabric-specific configurations
---
version: "1.0"
nodes:
# ================================================================
# Fabric (Top-level container for all fabric objects)
# ================================================================
- name: Fabric
namespace: Infra
description: EVPN-VXLAN Fabric definition
label: Fabric
icon: mdi--vector-polygon
include_in_menu: false
human_friendly_id:
- name__value
order_by:
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
unique: true
description: Fabric name (e.g., arista-evpn-fabric)
- name: description
kind: Text
optional: true
- name: underlay_protocol
kind: Dropdown
default_value: ebgp
choices:
- name: ebgp
label: eBGP
- name: ospf
label: OSPF
- name: isis
label: IS-IS
- name: overlay_protocol
kind: Dropdown
default_value: evpn
choices:
- name: evpn
label: EVPN
- name: ingress_replication
label: Ingress Replication
- name: anycast_gateway_mac
kind: Text
optional: true
description: "Shared MAC for anycast gateway (format: xxxx.xxxx.xxxx)"
relationships:
- name: spine_asn
peer: InfraAutonomousSystem
cardinality: one
optional: true
description: AS used by spine layer
- name: sites
peer: LocationSite
cardinality: many
optional: true
# ================================================================
# Underlay P2P Link
# ================================================================
- name: UnderlayLink
namespace: Infra
description: Point-to-point underlay link between devices
label: Underlay Link
icon: mdi--cable-data
include_in_menu: false
display_label: "{{ description__value }}"
attributes:
- name: description
kind: Text
description: Link description (e.g., spine1:eth1 <-> leaf1:eth11)
- name: mtu
kind: Number
default_value: 9214
relationships:
- name: fabric
peer: InfraFabric
cardinality: one
kind: Parent
optional: false
- name: local_device
peer: InfraDevice
identifier: underlay_link_local_device
cardinality: one
direction: outbound
- name: local_interface
peer: InfraInterfaceEthernet
identifier: underlay_link_local_interface
cardinality: one
direction: outbound
- name: local_ip_address
peer: InfraIPAddress
identifier: underlay_link_local_ip
cardinality: one
direction: outbound
- name: remote_device
peer: InfraDevice
identifier: underlay_link_remote_device
cardinality: one
direction: outbound
- name: remote_interface
peer: InfraInterfaceEthernet
identifier: underlay_link_remote_interface
cardinality: one
direction: outbound
- name: remote_ip_address
peer: InfraIPAddress
identifier: underlay_link_remote_ip
cardinality: one
direction: outbound
# ================================================================
# Host Connection
# ================================================================
- name: HostConnection
namespace: Infra
description: Host connection to fabric (single or dual-homed)
label: Host Connection
icon: mdi--desktop-tower
include_in_menu: false
human_friendly_id:
- hostname__value
display_label: "{{ hostname__value }}"
attributes:
- name: hostname
kind: Text
description: Connected host name
- name: description
kind: Text
optional: true
- name: connection_type
kind: Dropdown
default_value: dual_homed
choices:
- name: single_homed
label: Single-Homed
- name: dual_homed
label: Dual-Homed (MLAG)
- name: lacp_mode
kind: Dropdown
default_value: active
choices:
- name: active
label: Active
- name: passive
label: Passive
relationships:
- name: vlans
peer: InfraVLAN
cardinality: many
description: VLANs allowed on this connection
- name: mlag_interface
peer: InfraMlagInterface
cardinality: one
optional: true
description: MLAG interface for dual-homed
- name: lag_interface
peer: InfraInterfaceLag
cardinality: one
optional: true
description: LAG for single-homed

141
schemas/mlag.yml Normal file
View File

@@ -0,0 +1,141 @@
# MLAG Schema for EVPN-VXLAN Fabric
# Defines MLAG domain and peer configuration
---
version: "1.0"
nodes:
# ================================================================
# MLAG Domain
# ================================================================
- name: MlagDomain
namespace: Infra
description: MLAG domain configuration for leaf pair
label: MLAG Domain
icon: mdi--link-variant
include_in_menu: false
human_friendly_id:
- domain_id__value
display_label: "{{ domain_id__value }}"
attributes:
- name: domain_id
kind: Text
description: MLAG domain identifier (e.g., leafs)
- name: description
kind: Text
optional: true
- name: virtual_mac
kind: Text
description: "Shared virtual MAC (format: xxxx.xxxx.xxxx)"
- name: heartbeat_vrf
kind: Text
default_value: mgmt
description: VRF for heartbeat (typically mgmt)
- name: dual_primary_detection
kind: Boolean
default_value: true
- name: dual_primary_delay
kind: Number
default_value: 10
description: Delay in seconds before dual-primary action
- name: dual_primary_action
kind: Dropdown
default_value: errdisable
choices:
- name: errdisable
label: Error Disable Interfaces
- name: none
label: No Action
relationships:
- name: devices
peer: InfraDevice
cardinality: many
min_count: 2
max_count: 2
description: MLAG peer devices
- name: peer_vlan
peer: InfraVLAN
identifier: mlag_domain_peer_vlan
cardinality: one
direction: outbound
description: VLAN for MLAG peer-link control traffic
- name: ibgp_vlan
peer: InfraVLAN
identifier: mlag_domain_ibgp_vlan
cardinality: one
direction: outbound
optional: true
description: VLAN for iBGP peering between MLAG peers
# ================================================================
# MLAG Peer Configuration (per device)
# ================================================================
- name: MlagPeerConfig
namespace: Infra
description: MLAG configuration on a specific device
label: MLAG Peer Config
icon: mdi--server-network
include_in_menu: false
human_friendly_id:
- device__name__value
display_label: "{{ local_interface_ip__value }}"
attributes:
- name: local_interface_ip
kind: IPNetwork
description: IP on MLAG peer VLAN SVI
- name: peer_address
kind: IPHost
description: Peer's MLAG SVI IP address
- name: heartbeat_peer_ip
kind: IPHost
description: Peer's management IP for heartbeat
relationships:
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false
- name: mlag_domain
peer: InfraMlagDomain
cardinality: one
- name: local_interface
peer: InfraInterfaceVlan
cardinality: one
description: Local MLAG SVI
- name: peer_link
peer: InfraInterfaceLag
cardinality: one
description: Peer-link port-channel
# ================================================================
# MLAG Interface (MLAG-enabled LAG)
# ================================================================
- name: MlagInterface
namespace: Infra
description: MLAG interface configuration
label: MLAG Interface
icon: mdi--ethernet-cable
include_in_menu: false
display_label: "{{ mlag_id__value }}"
attributes:
- name: mlag_id
kind: Number
description: MLAG interface ID
- name: description
kind: Text
optional: true
- name: lacp_fallback_timeout
kind: Number
default_value: 5
description: LACP fallback timeout in seconds
- name: lacp_fallback_individual
kind: Boolean
default_value: true
relationships:
- name: mlag_domain
peer: InfraMlagDomain
cardinality: one
- name: lag_interfaces
peer: InfraInterfaceLag
cardinality: many
min_count: 1
max_count: 2
description: LAG interfaces on each MLAG peer

221
schemas/vlan_vxlan.yml Normal file
View File

@@ -0,0 +1,221 @@
# VLAN and VXLAN Schema for EVPN-VXLAN Fabric
# Defines VLAN, VNI mappings, and VTEP configuration
---
version: "1.0"
nodes:
# ================================================================
# VLAN
# ================================================================
- name: VLAN
namespace: Infra
description: Virtual LAN configuration
label: VLAN
icon: mdi--lan-connect
include_in_menu: false
human_friendly_id:
- vlan_id__value
order_by:
- vlan_id__value
display_label: "{{ vlan_id__value }} ({{ name__value }})"
attributes:
- name: vlan_id
kind: Number
unique: true
description: VLAN ID (1-4094)
- name: name
kind: Text
description: VLAN name
- name: description
kind: Text
optional: true
- name: status
kind: Dropdown
default_value: active
choices:
- name: active
label: Active
color: "#22c55e"
- name: reserved
label: Reserved
color: "#3b82f6"
- name: deprecated
label: Deprecated
color: "#ef4444"
- name: vlan_type
kind: Dropdown
default_value: standard
choices:
- name: standard
label: Standard
- name: mlag_peer
label: MLAG Peer
- name: mlag_ibgp
label: MLAG iBGP
description: VLAN purpose
- name: trunk_groups
kind: List
optional: true
description: "Trunk groups restricting VLAN propagation (e.g., mlag-peer)"
- name: stp_enabled
kind: Boolean
default_value: true
description: "Enable spanning-tree on this VLAN (set false for MLAG peer VLANs)"
relationships:
- name: vni
peer: InfraVNI
cardinality: one
optional: true
description: Associated L2VNI for VXLAN
- name: site
peer: LocationSite
cardinality: one
optional: true
# ================================================================
# VNI (VXLAN Network Identifier)
# ================================================================
- name: VNI
namespace: Infra
description: VXLAN Network Identifier
label: VNI
icon: mdi--tunnel-outline
include_in_menu: false
human_friendly_id:
- vni__value
order_by:
- vni__value
display_label: "{{ vni__value }}"
attributes:
- name: vni
kind: Number
unique: true
description: VNI value (1-16777215)
- name: description
kind: Text
optional: true
- name: vni_type
kind: Dropdown
default_value: l2vni
choices:
- name: l2vni
label: L2 VNI
color: "#3b82f6"
- name: l3vni
label: L3 VNI
color: "#22c55e"
description: VNI type for EVPN
relationships:
- name: vlan
peer: InfraVLAN
cardinality: one
optional: true
description: Associated VLAN for L2VNI
- name: vrf
peer: InfraVRF
cardinality: one
optional: true
description: Associated VRF for L3VNI
# ================================================================
# VTEP (VXLAN Tunnel Endpoint)
# ================================================================
- name: VTEP
namespace: Infra
description: VXLAN Tunnel Endpoint configuration
label: VTEP
icon: mdi--server-network-outline
include_in_menu: false
human_friendly_id:
- device__name__value
display_label: "{{ source_address__value }}"
attributes:
- name: source_address
kind: IPHost
description: VTEP source IP (typically from Loopback1)
- name: udp_port
kind: Number
default_value: 4789
- name: learn_restrict
kind: Dropdown
default_value: any
choices:
- name: any
label: Any
- name: flood
label: Flood
description: MAC learning restriction mode
relationships:
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false
- name: source_interface
peer: InfraInterfaceLoopback
cardinality: one
description: Source interface for VTEP
- name: vlan_vni_mappings
peer: InfraVlanVniMapping
cardinality: many
kind: Component
# ================================================================
# VLAN to VNI Mapping (per-device)
# ================================================================
- name: VlanVniMapping
namespace: Infra
description: VLAN to VNI mapping on a VTEP
label: VLAN-VNI Mapping
icon: mdi--swap-horizontal
include_in_menu: false
display_label: "{{ description__value }}"
attributes:
- name: description
kind: Text
optional: true
description: "Mapping description (e.g., VLAN 40 <-> VNI 10040)"
relationships:
- name: vtep
peer: InfraVTEP
cardinality: one
kind: Parent
optional: false
- name: vlan
peer: InfraVLAN
cardinality: one
- name: vni
peer: InfraVNI
cardinality: one
# ================================================================
# EVPN Instance (per VLAN)
# ================================================================
- name: EVPNInstance
namespace: Infra
description: EVPN instance configuration (route targets for L2 extension)
label: EVPN Instance
icon: mdi--cloud-sync
include_in_menu: false
display_label: "{{ route_distinguisher__value }}"
attributes:
- name: route_distinguisher
kind: Text
description: "Route Distinguisher (format: ASN:VNI or IP:VNI)"
- name: route_target_import
kind: Text
description: "Import Route Target (format: VNI:VNI)"
- name: route_target_export
kind: Text
description: "Export Route Target (format: VNI:VNI)"
- name: redistribute_learned
kind: Boolean
default_value: true
relationships:
- name: vlan
peer: InfraVLAN
cardinality: one
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false

124
schemas/vrf.yml Normal file
View File

@@ -0,0 +1,124 @@
# VRF Schema for EVPN-VXLAN Fabric
# Defines VRF and Route Target configuration for L3 VPN
---
version: "1.0"
nodes:
# ================================================================
# VRF (Virtual Routing and Forwarding)
# ================================================================
- name: VRF
namespace: Infra
description: Virtual Routing and Forwarding instance
label: VRF
icon: mdi--router
include_in_menu: false
human_friendly_id:
- name__value
order_by:
- name__value
display_label: "{{ name__value }}"
attributes:
- name: name
kind: Text
unique: true
description: VRF name
- name: description
kind: Text
optional: true
- name: route_distinguisher
kind: Text
optional: true
description: "Route Distinguisher (format: ASN:NN or IP:NN)"
- name: vrf_id
kind: Number
optional: true
description: VRF table ID
relationships:
- name: l3vni
peer: InfraVNI
cardinality: one
optional: true
description: L3 VNI for symmetric IRB
- name: import_targets
peer: InfraRouteTarget
identifier: vrf_import_targets
cardinality: many
direction: outbound
optional: true
- name: export_targets
peer: InfraRouteTarget
identifier: vrf_export_targets
cardinality: many
direction: outbound
optional: true
- name: interfaces
peer: InfraInterface
cardinality: many
optional: true
description: Interfaces assigned to this VRF
# ================================================================
# Route Target
# ================================================================
- name: RouteTarget
namespace: Infra
description: BGP Route Target for VPN import/export
label: Route Target
icon: mdi--target
include_in_menu: false
human_friendly_id:
- target__value
order_by:
- target__value
display_label: "{{ target__value }}"
attributes:
- name: target
kind: Text
unique: true
description: "Route Target value (format: ASN:NN or IP:NN)"
- name: description
kind: Text
optional: true
# ================================================================
# VRF Device Assignment
# ================================================================
- name: VRFDeviceAssignment
namespace: Infra
description: VRF assignment to a specific device
label: VRF Assignment
icon: mdi--router-network
include_in_menu: false
human_friendly_id:
- device__name__value
- vrf__name__value
display_label: "{{ device__name__value }} - {{ vrf__name__value }}"
attributes:
- name: route_distinguisher
kind: Text
optional: true
description: "Device-specific RD (overrides VRF default)"
relationships:
- name: vrf
peer: InfraVRF
cardinality: one
optional: false
- name: device
peer: InfraDevice
cardinality: one
kind: Parent
optional: false
- name: import_targets
peer: InfraRouteTarget
identifier: vrf_assignment_import_targets
cardinality: many
direction: outbound
optional: true
description: Device-specific import RTs
- name: export_targets
peer: InfraRouteTarget
identifier: vrf_assignment_export_targets
cardinality: many
direction: outbound
optional: true
description: Device-specific export RTs