Infragraph Export Design Summary¶
Overview¶
Export NetBox network topologies to infragraph format, enabling AI/HPC infrastructure modeling with automatic device grouping and intelligent name optimization.
Background¶
What is Infragraph?¶
Infragraph is a model-driven, vendor-neutral API for representing AI/HPC infrastructure using graph theory. It uses:
- Devices: Templates defining hardware types with components
- Components: Device parts (CPU, XPU, NIC, Port, Switch, Memory)
- Instances: Actual deployed copies of devices
- Links: Connection characteristics (bandwidth, latency)
- Edges: Connections between instance components
Key Insights from infragraph_service.py¶
The InfraGraphService module reveals that:
- Node naming convention:
{instance}.{device_idx}.{component}.{component_idx} - Service generates graph:
InfraGraphService.set_graph()converts Infrastructure → NetworkX - Built-in validation: We can validate our output by loading it back
- Component indexing is critical: Must map interface names to component indices precisely
- Indices must be 0-based and sequential: Component indices start at 0 and increment
Two-Phase Implementation¶
Phase A: Enhance NetworkX Graph¶
Preserve complete NetBox data in the existing NetworkX graph structure:
- Add interface metadata (speed, type, description, tags)
- Add cable attributes (type, status, length)
- Use device names (not IDs) for portable references
- Cache device type information
Benefit: Single code path benefits all exporters.
Phase B: Infragraph Export¶
Transform enhanced graph to infragraph format using the infragraph Python SDK.
Critical Difference: Unlike other exporters (clab, cml, cyjs) which use actual device interfaces, infragraph export uses NetBox Device Type templates to ensure consistent component indices across all devices of the same type. This means:
- Device interface templates are fetched from NetBox Device Types API
- Per-device customizations (modules, subinterfaces) are ignored
- Edges with interfaces not in device type templates are skipped with warnings
- Users must ensure NetBox device types are accurate and complete
Key Design Decisions¶
1. Automatic Instance Grouping¶
Approach: Group devices by (site, role, vendor, model), then compact names
# NetBox devices:
dc1-leaf01 (site=dc1, role=leaf, type=arista/dcs-7050sx-64)
dc1-leaf02 (site=dc1, role=leaf, type=arista/dcs-7050sx-64)
# Becomes infragraph instance:
instance_name: "dc1_leaf_7050" # Compacted
count: 2 # Two devices in group
No user configuration required - compaction routine automatically removes unnecessary parts.
2. Smart Name Compaction¶
Start maximal, then remove parts to find shortest conflict-free names:
Phase 1: Start with maximal name (site_role_vendor_model_full)
Phase 2: Remove parts only if uniqueness is preserved
Removal and compaction order:
- Drop site (if still unique)
- Drop vendor (if still unique)
- Compact model (full → extended → core) only if still unique
- Stop at the shortest unique form
Example scenarios:
| Scenario | NetBox Devices | Initial Names | Conflict? | Final Names |
|---|---|---|---|---|
| Single-site | dc1/leaf01 (7050sx), dc1/leaf02 (7050sx) | dc1_leaf_arista_7050sx64 | No | leaf_7050 (site+vendor removed, model compacted) |
| Multi-site same type | dc1/leaf01 (7050sx), dc2/leaf01 (7050sx) | dc1_leaf_arista_7050sx64, dc2_leaf_arista_7050sx64 | Yes | dc1_leaf_7050, dc2_leaf_7050 (site kept) |
| Same role, different models | leaf01 (7050sx), leaf02 (7050tx) | leaf_arista_7050sx64, leaf_arista_7050tx48 | Yes | leaf_7050sx, leaf_7050tx (extended model) |
| Multi-site different vendors | dc1/arista-leaf, dc2/cisco-leaf | dc1_leaf_arista_7050sx64, dc2_leaf_cisco_9300 | No | leaf_7050, leaf_9300 (site+vendor removed) |
See indexing.md Q4 (lines 1091-1235) for complete algorithm details.
3. Stable Instance Indexing¶
Request name-based ordering from NetBox API within each group:
# Request name-based ordering from NetBox API
devices = nb_session.dcim.devices.filter(..., ordering='name')
# Group: dc1_leaf_7050
# Devices are kept in NetBox API order (name-sorted by NetBox)
device_name: leaf01 → instance_index: 0
device_name: leaf02 → instance_index: 1
device_name: leaf03 → instance_index: 2
Benefits:
- Users have direct control via NetBox device naming
- Ordering depends on NetBox's implementation (typically case-sensitive alphabetical)
- Mirrors what users see in NetBox when sorted by name
- Portable across NetBox instances when names are preserved
Implementation Note:
- nrx explicitly requests
ordering='name'from NetBox API - The final ordering depends on how NetBox implements name sorting
- No local re-sorting in Python ensures consistency with NetBox
4. NetBox Metadata Preservation¶
Use infragraph's annotate_graph API to preserve NetBox metadata:
# Annotations on Instance nodes (device instances):
leaf_7050.0:
device_name: "leaf01"
site: "dc1"
role: "leaf"
platform: "arista-eos"
source_id: "42"
# Annotations on Device component nodes:
arista_dcs_7050sx_64.port.0:
interface_name: "Ethernet1"
arista_dcs_7050sx_64.port.1:
interface_name: "Ethernet2"
# ... defined once at Device level
# Instance components (leaf_7050.0.port.0) are NOT annotated
# They reference the Device
Two-file output:
topology.infragraph.json- Clean infrastructure model (no metadata)topology.infragraph.annotated.json- With NetBox device and instance annotations
Annotation strategy:
- Instance nodes: Annotated with device-specific metadata (device_name, site, role, platform)
- Device components: Annotated with interface names (once per device type)
- Instance components: NOT annotated (reference Device for interface names)
- Interface names come from NetBox Device Type definition (not individual devices)
- No per-device configuration data (MTU, descriptions, etc.) which can vary between devices
Queryable metadata: Use infragraph's query_graph API to:
- Find device instance by name:
device_name = "leaf01"→leaf_7050.0 - Find Device components:
interface_name = "Ethernet1"→arista_dcs_7050sx_64.port.0 - Reverse lookup:
arista_dcs_7050sx_64.port.5→interface_name = "Ethernet6"
5. Portable Identifiers (Use Names, Not IDs)¶
Problem: NetBox database IDs change between instances. Same topology in different NetBox instances will have different device/interface IDs, making exports non-portable.
Solution: Use names and sorted indices for all identifiers:
- ✅ Device names (portable across NetBox instances)
- ✅ Compacted instance names (portable)
- ✅ Alphabetically sorted interface names → component indices (portable)
- ❌ NetBox device IDs (database-specific, not used)
- ❌ NetBox interface IDs (database-specific, not used)
Result: Same NetBox topology data produces identical infragraph exports regardless of which NetBox instance it comes from, as long as device names are preserved.
Mapping Summary¶
| NetBox Concept | Infragraph Concept | Mapping |
|---|---|---|
| Device Type | Device (template) | Group by (vendor, model) |
| Device Type Interfaces | Component (Port) count | Fetched from Device Types API, sorted alphabetically |
| Devices (grouped) | Instance with count | Automatic grouping + compaction |
| Individual Device | Instance index | Preserve NetBox API order |
| Device Interface (actual) | Component index | Only if exists in Device Type template |
| Cable | Edge (ONE2ONE) | Point-to-point connection (if both interfaces in templates) |
| Interface speed | Link bandwidth | Kbps → Gbps conversion |
Important: Infragraph uses Device Type interface definitions, not actual device interfaces. Cables connecting interfaces not defined in device types are skipped.
Node Naming Convention¶
{instance_name}.{instance_index}.{component}.{component_index}
Examples:
leaf_7050.0.port.0 # leaf01's Ethernet1
leaf_7050.0.port.1 # leaf01's Ethernet2
leaf_7050.1.port.0 # leaf02's Ethernet1
dc1_spine_7280.0.port.10 # Multi-site export
Example Transformations¶
Single-Site Export¶
NetBox:
Site: dc1
leaf01 (arista/dcs-7050sx-64)
leaf02 (arista/dcs-7050sx-64)
spine01 (arista/dcs-7280sr-48c6)
Infragraph:
Instances:
leaf_7050: count=2 # Site removed (unique)
spine_7280: count=1 # Site removed (unique)
Nodes:
leaf_7050.0 → leaf01
leaf_7050.1 → leaf02
spine_7280.0 → spine01
Multi-Site Export (Same Devices)¶
NetBox:
Infragraph:
Instances:
dc1_leaf_7050: count=2 # Site kept (needed)
dc2_leaf_7050: count=2 # Site kept (needed)
Nodes:
dc1_leaf_7050.0 → dc1-leaf01
dc1_leaf_7050.1 → dc1-leaf02
dc2_leaf_7050.0 → dc2-leaf01
dc2_leaf_7050.1 → dc2-leaf02
Multi-Site Export (Different Devices)¶
NetBox:
Infragraph:
Instances:
leaf_7050: count=1 # Site removed (arista unique)
leaf_9300: count=1 # Site removed (cisco unique)
Nodes:
leaf_7050.0 → dc1-leaf01 (arista)
leaf_9300.0 → dc2-leaf01 (cisco)
Benefits¶
- ✅ Fully automatic - No user configuration for grouping
- ✅ Optimal readability - Shortest possible conflict-free names
- ✅ Portable - Consistent output across NetBox instances
- ✅ Stable - Device renames don't break indices
- ✅ Queryable - Reverse lookup via annotations
- ✅ Standard - Uses infragraph best practices
Usage¶
# Export to infragraph format
nrx --source netbox --output infragraph
# Output files:
# - topology.infragraph.json (clean infrastructure)
# - topology.infragraph.annotated.json (with NetBox metadata)
Troubleshooting¶
Warning: Skipped edges due to interfaces not in device type templates¶
Cause: The export found cables connecting interfaces that are not defined in the NetBox Device Type.
Example:
⚠ Warning: Skipped 3 edges due to interfaces not in device type templates:
- leaf01:Ethernet49 (not in device type)
- spine01:Management0 (not in device type)
- leaf02:Ethernet1.100 (not in device type)
Solution:
- Review the NetBox Device Type definition for the affected devices
- Add missing interfaces to the Device Type template in NetBox
- Re-run the export
Why this happens:
- Device has a custom module or add-on interface not in the device type
- Device has subinterfaces (e.g.,
Ethernet1.100) not defined in device type - Device has management interfaces not included in device type template
Expected behavior: Infragraph requires consistent device templates. Per-device customizations are intentionally ignored to ensure all devices of the same type have identical component structures.
Interface Ordering and Component Indices¶
How component indices are assigned:
Component indices for interfaces are assigned based on the order of interfaces in the NetBox Device Type definition, not by alphabetical or natural sorting.
Example:
NetBox Device Type: Arista DCS-7050SX-64
Interface order in NetBox:
1. Management1 → component index 0
2. Ethernet1 → component index 1
3. Ethernet2 → component index 2
...
50. Ethernet49 → component index 49
Important notes:
- nrx preserves the exact interface order from NetBox device types
- No local sorting is performed (alphabetical, natural, or otherwise)
- Component indices will shift if you reorder interfaces in the NetBox device type
- Users should ensure device type interfaces are ordered correctly in NetBox before export
Why this approach:
- NetBox is the canonical source of truth for device type definitions
- Users have full control over interface ordering in NetBox UI
- Avoids issues with complex interface naming schemes (e.g.,
Ethernet1/10vsEthernet1/2) - Consistent behavior across different NetBox versions
References¶
- Detailed Design: indexing.md
- Implementation Plan: implementation.md
- Infragraph Docs: https://infragraph.dev/
- Infragraph SDK: https://pypi.org/project/infragraph/