ank_pydantic

Phase 59/62 (100%)

← Back to Projects


The Insight

Network topology modeling typically forces a choice between the speed of untyped graph libraries (NetworkX) and the rigidity of database-backed sources of truth. ank-pydantic eliminates this trade-off by using Pydantic for schema validation and a high-performance Rust core (petgraph) for graph traversals.

Quick Facts

   
Status Phase 59/62 (100%)
Language N/A
Started 2026

What This Is

A Python library for modeling and querying network topologies with type-safe Pydantic models and a high-performance Rust core. Expressive Python API backed by blazing-fast graph algorithms, with automatic configuration generation for multi-vendor network deployments.

Key Features

Examples

Service Provider Core: IS-IS + MPLS + iBGP

Input Topology (transitnet.yaml):

topology:
  - metadata:
      name: TransitNet SP Core
      organisation: TransitNet
      asn: 65000

  - nodes:
      - P1:
          role: core
          data:
            pop: West
            platform: iosxr
            loopback: 10.0.0.1/32
          endpoints:
            - Gi0/0/0/0  # to P3
            - Gi0/0/0/1  # to P5
            - Gi0/0/0/2  # to PE1

      - P3:
          role: core
          data:
            pop: East
            platform: iosxr
            loopback: 10.0.0.3/32
          endpoints:
            - Gi0/0/0/0  # to P1
            - Gi0/0/0/2  # to PE3

      - PE1:
          role: pe
          data:
            pop: West
            platform: iosxr
            loopback: 10.0.0.11/32
          endpoints:
            - Gi0/0/0/0  # to P1

  - links:
      - [P1, Gi0/0/0/0, P3, Gi0/0/0/0]   # West-East core
      - [P1, Gi0/0/0/2, PE1, Gi0/0/0/0]  # Core-PE

Build Protocol Layers:

from ank_pydantic import Topology
from ank_pydantic.blueprints.designs.isis import build_isis_layer
from ank_pydantic.blueprints.designs.mpls import build_mpls_layer

# ank_pydantic
topology = Topology.from_yaml("transitnet.yaml")

# ank_pydantic
isis_layer = build_isis_layer(
    topology,
    level=2,
    area="49.0001",
    parent_layer="physical"
)

# ank_pydantic
mpls_layer = build_mpls_layer(
    topology,
    igp_layer="isis",
    layer_name="mpls"
)

Generated Configuration (P1 - Cisco IOS-XR):

hostname P1
!
interface Loopback0
 ipv4 address 10.0.0.1 255.255.255.255
!
interface GigabitEthernet0/0/0/0
 description to P3
 ipv4 address 10.1.0.1 255.255.255.252
!
interface GigabitEthernet0/0/0/2
 description to PE1
 ipv4 address 10.1.0.5 255.255.255.252
!
router isis CORE
 is-type level-2-only
 net 49.0001.0100.0000.0001.00
 address-family ipv4 unicast
  metric-style wide
 !
 interface Loopback0
  passive
  address-family ipv4 unicast
 !
 interface GigabitEthernet0/0/0/0
  point-to-point
  address-family ipv4 unicast
   metric 10
  !
 !
 interface GigabitEthernet0/0/0/2
  point-to-point
  address-family ipv4 unicast
   metric 10
  !
 !
!
mpls ldp
 router-id 10.0.0.1
 interface GigabitEthernet0/0/0/0
 !
 interface GigabitEthernet0/0/0/2
 !
!

L3VPN Configuration

Input: Add customer sites to PE routers:

# ank_pydantic
- nodes:
    - CE1:
        role: ce
        data:
          organisation: NetCorp
          asn: 65100
          loopback: 192.168.1.1/32
        endpoints:
          - Gi0/0

    - CE2:
        role: ce
        data:
          organisation: NetCorp
          asn: 65100
          loopback: 192.168.2.1/32
        endpoints:
          - Gi0/0

- links:
    - [PE1, Gi0/0/0/1, CE1, Gi0/0]  # PE-CE link
    - [PE3, Gi0/0/0/1, CE2, Gi0/0]  # PE-CE link

Build L3VPN Layer:

from ank_pydantic.blueprints.designs.l3vpn import build_l3vpn_layer

# ank_pydantic
l3vpn_layer = build_l3vpn_layer(
    topology,
    service_name="NetCorp-L3VPN",
    customer="NetCorp",
    customer_asn=65100,
    provider_asn=65000,
    vpn_id=100
)

Generated VRF Configuration (PE1):

vrf NETCORP
 address-family ipv4 unicast
  import route-target
   65000:100
  !
  export route-target
   65000:100
  !
 !
!
interface GigabitEthernet0/0/0/1
 description to CE1 (NetCorp)
 vrf NETCORP
 ipv4 address 10.100.1.1 255.255.255.252
!
router bgp 65000
 vrf NETCORP
  rd 65000:100
  address-family ipv4 unicast
   redistribute connected
  !
  neighbor 10.100.1.2
   remote-as 65100
   description CE1
   address-family ipv4 unicast
    route-policy NETCORP-IN in
    route-policy NETCORP-OUT out
   !
  !
 !
!

Containerlab Deployment

Export to Containerlab:

from ank_pydantic.blueprints.environments import get_environment

# ank_pydantic
env = get_environment('containerlab')

# ank_pydantic
artifacts = env.generate(topology)

# ank_pydantic
with open("transitnet.clab.yml", "w") as f:
    f.write(artifacts.files['topology.clab.yml'])

Generated Containerlab File (transitnet.clab.yml):

name: transitnet
mgmt:
  network: mgmt
  ipv4-subnet: 172.20.20.0/24

topology:
  nodes:
    P1:
      kind: cisco_xrv9k
      image: vrnetlab/vr-xrv9k:7.3.2
      mgmt-ipv4: 172.20.20.11
      binds:
        - ./configs/P1.cfg:/config/startup-config.cfg

    P3:
      kind: cisco_xrv9k
      image: vrnetlab/vr-xrv9k:7.3.2
      mgmt-ipv4: 172.20.20.13
      binds:
        - ./configs/P3.cfg:/config/startup-config.cfg

    PE1:
      kind: cisco_xrv9k
      image: vrnetlab/vr-xrv9k:7.3.2
      mgmt-ipv4: 172.20.20.21
      binds:
        - ./configs/PE1.cfg:/config/startup-config.cfg

  links:
    - endpoints: ["P1:Gi0/0/0/0", "P3:Gi0/0/0/0"]
    - endpoints: ["P1:Gi0/0/0/2", "PE1:Gi0/0/0/0"]

Deploy and Verify:

# ank_pydantic
sudo containerlab deploy -t transitnet.clab.yml

# ank_pydantic
sudo containerlab inspect -t transitnet.clab.yml

# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic

# ank_pydantic
docker exec -it clab-transitnet-P1 show isis neighbors

# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic

# ank_pydantic
docker exec -it clab-transitnet-P1 show mpls ldp neighbor

# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic
# ank_pydantic

Query API Usage

Composable queries with Rust-backed execution:

# ank_pydantic
core_routers = topology.query.nodes().where(
    lambda n: n.data.role == "core" and n.data.pop == "North"
).models()

# ank_pydantic
inter_pop_links = topology.query.links().where(
    lambda l: l.data.link_type == "long-haul"
).count()

# ank_pydantic
mpls_devices = topology.layer("mpls").nodes().where(
    mpls_enabled=True
).ids()

Integration with NetVis

Export for visualization:

# ank_pydantic
topology.export_for_netvis(
    "output.json",
    layout="hierarchical",
    node_metadata=True
)

NetVis applies advanced layout algorithms to produce publication-quality diagrams.


YAML Topology Format

Define topologies in YAML for rapid prototyping:

topology:
  - metadata:
      name: TransitNet SP Core
      organisation: TransitNet
      asn: 65000

  - nodes:
      - P1:
          role: core
          data:
            pop: West
            platform: iosxr
            loopback: 10.0.0.1/32
          endpoints:
            - Gi0/0/0/0  # to P3
            - Gi0/0/0/1  # to P5

      - PE1:
          role: pe
          data:
            pop: West
            platform: iosxr
            loopback: 10.0.0.11/32
          endpoints:
            - Gi0/0/0/0  # to P1
            - Gi0/0/0/1  # customer-facing

  - links:
      - [P1, Gi0/0/0/0, P3, Gi0/0/0/0]   # West-East
      - [P1, Gi0/0/0/1, P5, Gi0/0/0/0]   # West-North
      - [P1, Gi0/0/0/2, PE1, Gi0/0/0/0]  # Core-PE

Load and process:

topology = Topology.from_yaml("transitnet.yaml")

# ank_pydantic
isis_layer = build_isis_layer(topology, level=2, area="49.0001")
mpls_layer = build_mpls_layer(topology, igp_layer="isis")

# ank_pydantic
env = get_environment('containerlab')
artifacts = env.generate(topology)

Available Blueprints

Pre-built design functions for common network patterns:

Blueprint Purpose Key Features
IS-IS IGP routing Multi-level (L1, L2, L1/L2), area assignment, NET generation
MPLS/LDP Label switching Follows IGP adjacencies, label range configuration, targeted LDP
L3VPN VPN services VRF configuration, RD/RT generation, PE-CE sessions
EVPN L2/L3 overlay VXLAN, MAC/IP routes, multi-tenancy
IXP Peering fabric Route server, bilateral peering, BGP communities
Data Center Spine-leaf CLOS topology, ECMP, BGP unnumbered

Each blueprint provides:


Current Status

Feature-complete, final polish and documentation before 1.0 release.

Tech Stack

Python (Pydantic), Rust core (petgraph-backed), PyO3 bindings


← Back to Network Automation ← Back to Projects