Architecture overview
Assumes familiarity with Infrahub and Python. If you only want to use the system, start with Quick Start.
The solution is a repository of schemas, generators, and transforms loaded on top of the Infrahub platform. The sections below cover its components, data model, and the generator and transform pipelines.
System componentsβ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Infrahub Platform β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
β β Neo4j Graph β β PostgreSQL β β Object Store β β
β β Database β β (Metadata) β β (Hostvars, Configs) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
β β Redis Cache β β RabbitMQ β β Infrahub Server β β
β β β β (Queue) β β (API + Git Backend) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Repository Solution β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
β β Schemas β β Generators β β Transforms β β
β β (YAML DSL) β β (Python) β β (Python + Jinja2) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
β β Object Data β β Queries β β Core Library β β
β β (Seed YAML) β β (GraphQL) β β (src/solution_arista_avd) β β
β βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data model hierarchyβ
The system models a 3-tier datacenter network fabric:
NetworkFabric (e.g., "Fabric-L3LS-MultiPod-A")
βββ NetworkPod (e.g., "Pod-A1", "Pod-A2")
β βββ LocationRack (e.g., "Rack-A1-01", "Rack-A1-02")
β β βββ DcimDevice [leaf] (e.g., "leaf-A1-01-1")
β β βββ InterfacePhysical (e.g., "Ethernet1")
β β βββ NetworkLink β remote interface
β β βββ IpamIPAddress
β β ββ DcimDevice [spine] (e.g., "spine-A1-1")
βββ DcimDevice [super_spine] (e.g., "ss-A-1")
IP address managementβ
Fabric-level pool allocation:
NetworkFabric
βββ loopback_pool: CoreIPPrefixPool
β βββ Internal CoreIPAddressPool wrapper: Loopback0 addresses
βββ vtep_pool: CoreIPPrefixPool
β βββ Internal CoreIPAddressPool wrapper: VTEP loopback addresses
βββ uplink_pool: CoreIPPrefixPool
β βββ Prefix allocations for point-to-point links
βββ mgmt_pool: CoreIPAddressPool
β βββ OOB management addresses
βββ CoreNumberPool: ASN Pool (65000-65999)
β βββ Tier-aware eBGP ASN allocation: shared super-spine ASN per fabric, shared spine ASN per pod, leaf ASNs per device or MLAG domain
βββ CoreNumberPool: Node ID Pool (1-65535)
βββ Per-device unique identifier
Generator pipelineβ
Generators run in sequence to build infrastructure:
βββββββββββββββββββββββββββ
β 1. FabricGenerator β Triggered on: NetworkFabric
β - Resolve fabric pools β Creates: Super-spine devices
β - Create super-spines β
βββββββββββββ¬ββββββββββββββ
βΌ
βββββββββββββββββββββββββββ
β 2. PodGenerator β Triggered on: NetworkPod
β - Create spine devices β Creates: Spine switches
β - Link to super-spines β
βββββββββββββ¬ββββββββββββββ
βΌ
βββββββββββββββββββββββββββ
β 3. RackGenerator β Triggered on: LocationRack
β - Create leaf devices β Creates: Leaf switches
β - Link to spines β
βββββββββββββ¬ββββββββββββββ
βΌ
βββββββββββββββββββββββββββ
β 4. AVD Generators β Triggered on: NetworkFabric/Device
β - Build hostvars β Creates: AVD configs
β - Generate struct cfg β
βββββββββββββββββββββββββββ
Two further generators sit outside this chain:
ServerCablingGenerator(onComputePhysicalServer) cables a server to the leaves in its rack, then reconciles its LAGs and VLANs and re-triggers hostvar generation for those leaves.BackfillStructuredConfigGenerator(onAvdStructuredConfigFile) runs in the opposite direction, reading AVD's structured-config output back into IPAM, interface, BGP, and routing objects.
See Generators.
Transform pipelineβ
Transforms convert data to artifacts:
ββββββββ ββββββββββββ ββββββββββββββββββββββ βββββββββββββββββββ
β GraphQL Query β βββΆ β Transform Logic β βββΆ β Output Artifactβ
β (Data Fetch) β β (Python/Jinja2) β β (Config/Doc) β
ββββββββββββββββββββ ββββββββββββββββββββββ βββββββββββββββββββ
Examples:
- DcimInterface β ComputedInterfaceDescription β "β device:interface"
- NetworkFabric β CablingPlan β CSV cabling matrix
- DcimDevice β AvdEosConfig β EOS CLI configuration
- NetworkFabric β AvdFabricDoc β Markdown documentation
- DcimDevice β AvdAntaCatalog β ANTA test catalog (YAML)
- NetworkFabric β ContainerLabTopology β ContainerLab topology (YAML)
Validation pipelineβ
Alongside transforms, proposed-change validation runs checks β Python routines that report pass, information, or error rather than producing an artifact. The repository ships one, cv-config-validation, which deploys the rendered EOS configs into a CloudVision workspace and blocks the proposed change on a failed build. See Checks.
Checksum-based change detectionβ
Generators use checksums to avoid redundant regeneration:
class GeneratorMixin:
def calculate_checksum(self, related_node_ids: list[str]) -> str:
"""Create deterministic hash from related node IDs"""
return hashlib.sha256("".join(sorted(related_node_ids))).hexdigest()
# Usage in generator:
new_checksum = self.calculate_checksum([pod.id, device.id, ...])
if new_checksum != target.checksum:
# Regenerate
target.checksum = new_checksum
Configuration filesβ
| File | Role |
|---|---|
.infrahub.yml | Register queries, generators, transforms, artifacts |
repository.yml | Define repository as CoreRepository in Infrahub |
docker-compose.yml | Orchestrate Infrahub services |
pyproject.toml | Python dependencies and tool configuration |
Docker service stackβ
services:
infrahub-server: # Main API server
infrahub-git: # Git backend for repository
infrahub-worker: # Async task execution
neo4j: # Graph database
postgres: # Relational metadata
redis: # Cache layer
rabbitmq: # Message queue
Development workflowβ
1. Edit schema (schemas/*.yml)
β
2. Load schema: inv load-schema
β
3. Edit generator/transform code
β
4. Test: pytest tests/
β
5. Lint: inv lint
β
6. Reload: inv load
β
7. Run generators via UI
Pool role resolutionβ
Fabric and pod IP pool intent is role-driven. NetworkFabric.fabric_ip_pools is the authoritative fabric collection for Management, Loopback, Loopback VTEP, Fabric Point-to-Point, DCI, and Fabric Supernet roles. NetworkPod.pod_ip_pools is the authoritative pod collection for pod-scoped Loopback, Loopback VTEP, Fabric Point-to-Point, MLAG, and MLAG Peering roles.
Validation resolves a pool's purpose from the roles on its backing IpamPrefix resources. The proposed-change check rejects duplicate authoritative roles, mixed-role pools, non-IP pool members, pod management pools, and pod prefixes that are not contained by the matching parent fabric pool.
During migration, legacy fabric and pod pool relationships are still present and object data is dual-populated. Generators prefer collection relationships and fall back to legacy relationships only when needed.
Sourceβ
- Infrahub configuration:
.infrahub.ymlβ the queries, generators, transforms, and artifact definitions registered with Infrahub. - Schemas:
schemas/β the data model. - Generators:
generators/β Python generator classes. - Transforms:
transforms/β Python transform classes and templates. - Checks:
checks/β proposed-change validation, currently CloudVision. - Playbooks:
ansible/β the tree Semaphore runs for EOS config deployment and ContainerLab staging. - Core library:
src/solution_arista_avd/β shared protocols, AVD utilities, sorting, addressing. - Service portal:
service_catalog/β Streamlit UI that orchestrates the portal workflows.