## Summary
- Add `local_identifier` attribute + `uniqueness_constraints` + `human_friendly_id` to **InfraVlanVniMapping**, **InfraEVPNInstance**, **InfraMlagInterface**, and **InfraUnderlayLink**, following the same pattern already used for `InfraBGPPeerGroup` and `InfraBGPSession`
- Populate `local_identifier` in all corresponding object YAML files with deterministic composite keys so Infrahub can upsert objects during Repository backend sync instead of creating duplicates
## Schema changes
| Schema file | Model | human_friendly_id |
|---|---|---|
| `infrahub/schemas/vlan_vxlan.yml` | `InfraVlanVniMapping` | `local_identifier__value` |
| `infrahub/schemas/vlan_vxlan.yml` | `InfraEVPNInstance` | `local_identifier__value` |
| `infrahub/schemas/mlag.yml` | `InfraMlagInterface` | `local_identifier__value` |
| `infrahub/schemas/extensions.yml` | `InfraUnderlayLink` | `local_identifier__value` |
## Object file changes
| Object file | Kind | Key format | Example |
|---|---|---|---|
| `infrahub/objects/06-vlans-vxlan.yml` | `InfraVlanVniMapping` | `{device}__vlan{vlan_id}__vni{vni_id}` | `leaf1__vlan40__vni110040` |
| `infrahub/objects/06-vlans-vxlan.yml` | `InfraEVPNInstance` | `{device}__vlan{vlan_id}` | `leaf1__vlan40` |
| `infrahub/objects/12-mlag.yml` | `InfraMlagInterface` | `mlag{id}__{device1}-{device2}` | `mlag1__leaf1-leaf2` |
| `infrahub/objects/14-fabric-links.yml` | `InfraUnderlayLink` | `{local_dev}-{local_intf}__{remote_dev}-{remote_intf}` | `spine1-eth1__leaf1-eth11` |
Note: `InfraMlagInterface` objects (4 entries, one per MLAG pair) and `InfraUnderlayLink` objects (16 entries, all spine↔leaf P2P links) are new additions to their respective files.
## Test plan
- [x] `infrahubctl schema load infrahub/schemas/*.yml` succeeds without errors
- [x] `infrahubctl object load infrahub/objects/06-vlans-vxlan.yml` succeeds
- [x] `infrahubctl object load infrahub/objects/12-mlag.yml` succeeds
- [x] `infrahubctl object load infrahub/objects/14-fabric-links.yml` succeeds
- [x] Re-running the same load is idempotent (no duplicate objects created)
- [x] Gitea Repository backend sync completes without import errors
242 lines
7.0 KiB
YAML
242 lines
7.0 KiB
YAML
# 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
|
|
- name: svi_interfaces
|
|
peer: InfraInterfaceVlan
|
|
identifier: vlan__svi
|
|
cardinality: many
|
|
kind: Generic
|
|
description: SVI interfaces for this VLAN
|
|
|
|
# ================================================================
|
|
# 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
|
|
uniqueness_constraints:
|
|
- ["local_identifier__value"]
|
|
human_friendly_id:
|
|
- local_identifier__value
|
|
display_label: "{{ description__value }}"
|
|
attributes:
|
|
- name: local_identifier
|
|
kind: Text
|
|
description: "Unique identifier combining device name, VLAN ID and VNI (e.g. leaf1__vlan40__vni110040)"
|
|
- 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
|
|
uniqueness_constraints:
|
|
- ["local_identifier__value"]
|
|
human_friendly_id:
|
|
- local_identifier__value
|
|
display_label: "{{ route_distinguisher__value }}"
|
|
attributes:
|
|
- name: local_identifier
|
|
kind: Text
|
|
description: "Unique identifier combining device name and VLAN ID (e.g. leaf1__vlan40)"
|
|
- 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
|