Skip to main content

Role mapping

Developer Guide

Role names are PyAVD-version-sensitive — see the overview for the pinned version.

Infrahub's DcimDevice.role.value is a string enum that the hostvars generator maps to a PyAVD type. The mapping lives in src/solution_arista_avd/avd.py:

Table​

Infrahub rolePyAVD typePrimary scenario
super_spinesuper-spineL3LS, 5-stage Clos
spinespineL3LS
leafl3leafL3LS
border_leafl3leafDual-DC (DCI)
l2leafl2leafL3LS access, L2LS access, campus access
l2spinel2spineStandalone L2LS fabric
l3spinel3spineL2LS (L3 variant), campus core
ppISIS-LDP IPVPN (provider core)
pepeISIS-LDP IPVPN (provider edge)
rrrrISIS-LDP IPVPN route reflector

All PyAVD type values above are valid entries in the pinned PyAVD default node_type_keys. Roles beyond l3leaf/l2leaf are the schema anchors for the AVD example scenarios; the scenario-specific rendering behaviour is delivered either natively or through the avd_custom_hostvars escape hatch — see Extending the Pipeline.

The mapping in code​

# src/solution_arista_avd/avd.py
ROLE_TO_AVD_TYPE: dict[str, str] = {
"super_spine": "super-spine",
"spine": "spine",
"leaf": "l3leaf",
"border_leaf": "l3leaf",
"l2leaf": "l2leaf",
"l2spine": "l2spine",
"l3spine": "l3spine",
"p": "p",
"pe": "pe",
"rr": "rr",
}


def get_avd_type(role: str) -> str:
if role not in ROLE_TO_AVD_TYPE:
msg = f"Unknown device role: {role}"
raise ValueError(msg)
return ROLE_TO_AVD_TYPE[role]

An unrecognized role raises ValueError at generation time — Phase 1 fails for that device.

Underlay-driven role selection​

The four non-L3LS example designs do not set spine/leaf roles manually. Instead the upstream generator derives them from the fabric underlay, so the same spine/leaf topology renders different device types per design:

Fabric underlaySpine-tier roleLeaf-tier roleExample design
nonel2spinel2leafStandalone L2LS
ospfl3spinel2leafCampus
isis-ldpppeMPLS ISIS-LDP IPVPN

These come from SPINE_ROLE_BY_UNDERLAY and LEAF_ROLE_BY_UNDERLAY in avd.py. The selection is gated to non-L3LS underlays only: a routed L3LS fabric (underlay ebgp) is not in either map, so it falls back to the default spine / leaf roles.

MLAG in non-L3LS designs​

MLAG_MAIN_TIER_ROLES (l2leaf, l2spine, l3spine) is the main tier of the non-L3LS designs that forms MLAG pairs. When the fabric underlay is one of SPINE_UPLINK_UNDERLAYS (none, ospf, isis-ldp), devices in these roles render node-group / peer-link / MLAG-domain configuration — the same as the L3LS leaf family. The gate leaves the L3LS access-tier l2leaf (pure access under EVPN) unaffected.

Which generator forms the pair depends on the tier:

TierGeneratorPeer-link source
l2leaf (rack tier)generate-rackHighest-numbered free access ports — the arista-7050sx3-48yc8c l2leaf model ships no dedicated mlag_peer interfaces
l2spine (pod tier, underlay none)generate-podHighest-numbered free super-spine-facing ports, unused in a standalone L2LS fabric (it has no super-spines)

Both go through the shared assign_mlag_peer_interfaces helper on the generator mixin, so the choice is deterministic (ordered by the interface's computed index) and idempotent — a re-run converts nothing further. The l2spine pair has no BGP ASN: a pure Layer-2 tier runs no BGP.

Per-tier spanning-tree priorities​

Network.SpanningTreePriority links a fabric to a per-role MSTP priority. Its role dropdown covers super_spine, spine, leaf, l2leaf and — for the non-L3LS designs — l2spine and l3spine. The L2LS example sets l2spine: 4096 / l2leaf: 16384, which the hostvars generator emits as each tier's spanning_tree_priority.

Role implications​

The role governs these downstream behaviors in the hostvars generator and in PyAVD itself:

RoleUplink sourceGets EVPN data?MLAG?
super_spine— (top of fabric)NoNo
spinesuper_spineNoNo
leafspineYesYes (if peer set)
border_leafspineYes, including DCI links and EVPN Gateway when the device is a member of an EvpnGatewayGroupYes (if peer set)
l2leafleafNo (skipped)Yes (if peer set)

See Hostvars Reference for exactly which fields each role emits.

Tests​

The role mapping is exercised by:

Adding a new role​

See Extending the Pipeline → Add a new device role.