[Day #25 PyATS Series] OSPF Adjacency Validation Across Cisco/Arista/Palo Alto/Fortigate Using pyATS [Python for Network Engineer]
Table of Contents
Introduction
Open Shortest Path First (OSPF) is a critical Interior Gateway Protocol (IGP) for routing within an enterprise or data center network. Verifying OSPF adjacencies manually across multi-vendor environments—Cisco, Arista, Palo Alto, and Fortinet—can be time-consuming and error-prone. With pyATS, network engineers can automate OSPF adjacency validation, ensuring stable routing and preventing network outages.
This tutorial, designed for Python for Network Engineer learners, shows how to build a vendor-agnostic pyATS script that validates OSPF neighbor states across multiple platforms. By automating adjacency checks, you improve network visibility, minimize misconfiguration risks, and speed up troubleshooting efforts.
Topology Overview
- Cisco Router1 (IOS-XE) – Area 0
- Cisco Router2 (IOS-XR) – Area 0
- Arista Switch1 (EOS) – Area 0
- Palo Alto Firewall1 (PAN-OS) – Area 0
- Fortinet Firewall2 (FortiOS) – Area 0

Goal: Validate OSPF adjacencies across all devices, detecting down or incomplete states.
Topology & Communications
- Protocol: SSH-based CLI connections
- pyATS Parsers: Used to parse
show ospf neighbor
or equivalent vendor commands - Authentication: Defined in
testbed.yml
The script will:
- Connect to each device
- Run OSPF neighbor commands per vendor
- Parse adjacency state (Full, 2-Way, Down)
- Generate a consolidated report of OSPF neighbor health
Workflow Script
from genie.testbed import load import json def get_ospf_neighbors(device): device.connect(log_stdout=False) if device.os in ['iosxe', 'iosxr']: output = device.parse('show ip ospf neighbor') elif device.os == 'eos': output = device.parse('show ip ospf neighbor') elif device.os == 'panos': output = device.parse('show routing protocol ospf neighbor') elif device.os == 'fortinet': output = device.parse('get router info ospf neighbor') else: output = {} device.disconnect() return output def summarize_ospf(output): summary = {} for neighbor_ip, details in output.get('neighbors', {}).items(): state = details.get('state', 'unknown') summary[neighbor_ip] = state return summary if __name__ == "__main__": testbed = load('testbed.yml') devices = testbed.devices ospf_report = {} for name, device in devices.items(): print(f"Checking OSPF neighbors on {name}...") neighbor_output = get_ospf_neighbors(device) ospf_report[name] = summarize_ospf(neighbor_output) with open('ospf_neighbor_report.json', 'w') as f: json.dump(ospf_report, f, indent=4) print(json.dumps(ospf_report, indent=4))
Explanation by Line
- Imports: Load testbed and JSON for structured outputs.
- get_ospf_neighbors:
- Connects to each device and runs OS-specific OSPF command.
- Parses results into structured data.
- summarize_ospf: Extracts neighbor IP and OSPF state.
- Main loop: Iterates through devices, collects data, writes JSON report.
testbed.yml Example
testbed: name: ospf_adjacency_validation devices: Router1: os: iosxe type: router connections: cli: protocol: ssh ip: 192.168.100.1 credentials: default: username: admin password: cisco123 Router2: os: iosxr type: router connections: cli: protocol: ssh ip: 192.168.100.2 credentials: default: username: admin password: cisco123 Switch1: os: eos type: switch connections: cli: protocol: ssh ip: 192.168.100.3 credentials: default: username: admin password: arista123 Firewall1: os: panos type: firewall connections: cli: protocol: ssh ip: 192.168.100.4 credentials: default: username: admin password: paloalto123 Firewall2: os: fortinet type: firewall connections: cli: protocol: ssh ip: 192.168.100.5 credentials: default: username: admin password: fortinet123
Post-validation CLI Screenshots (Expected Output)
Cisco IOS-XE:
Router1# show ip ospf neighbor Neighbor ID Pri State Dead Time Address Interface 2.2.2.2 1 FULL/DR 00:00:34 192.168.100.2 Gig0/0
Arista EOS:
Switch1# show ip ospf neighbor Neighbor ID Pri State Dead Time Address Interface 1.1.1.1 1 FULL 00:00:30 192.168.100.1 Ethernet1
Palo Alto:
> show routing protocol ospf neighbor Neighbor: 192.168.100.1 State: Full Interface: ethernet1/1
Script Output:
{ "Router1": {"192.168.100.2": "FULL/DR"}, "Switch1": {"192.168.100.1": "FULL"}, "Firewall1": {"192.168.100.1": "Full"} }
FAQs
1. How does pyATS handle different OSPF CLI outputs from multiple vendors?
pyATS uses Genie parsers that are designed for each supported OS (Cisco IOS-XE, IOS-XR, Arista EOS, Palo Alto, Fortinet). This ensures that the script can interpret different CLI outputs and present standardized neighbor information.
2. Can the script detect partial OSPF adjacencies like 2-Way or Init states?
Yes. The script captures all adjacency states (Down, Init, 2-Way, ExStart, Full), allowing you to detect when neighbors are not fully adjacent and potentially diagnose issues early.
3. Does this approach support OSPFv3 for IPv6 networks?
Yes. With minor changes to the OSPF command used for each device, pyATS can parse OSPFv3 neighbor information, making it suitable for IPv6-enabled environments.
4. How can I validate the number of expected neighbors per device?
You can extend the script to include an expected neighbors list for each device. The script can then compare discovered neighbors against these expectations and alert you if a neighbor is missing.
5. Is it possible to visualize OSPF adjacency health over time?
Yes. The JSON output generated by the script can be fed into visualization platforms like Grafana or Kibana to create dashboards that show adjacency states and historical trends.
6. Can I run this script safely in a production network?
Absolutely. The script only executes read-only OSPF show commands, ensuring no changes are made to production configurations or traffic forwarding.
7. How scalable is this solution for large networks?
pyATS supports connecting to hundreds of devices in parallel. With proper testbed configuration and distributed execution, it scales well for enterprise and service provider networks.
8. Can it detect OSPF flapping neighbors automatically?
Yes. By scheduling the script to run periodically and analyzing adjacency state changes over time, you can detect and troubleshoot flapping neighbors efficiently.
YouTube Link
Watch the Complete Python for Network Engineer: OSPF Adjacency Validation Across Cisco/Arista/Palo Alto/Fortigate Using pyATS [Python for Network Engineer] Lab Demo & Explanation on our channel:
Join Our Training
Ensuring OSPF stability is vital for maintaining optimal routing in enterprise networks. Trainer Sagar Dhawan offers a comprehensive 3-month instructor-led course covering Python, Ansible, APIs, and Cisco DevNet for Network Engineers. Learn practical skills to automate OSPF checks and more.
Join Our Training to elevate your automation expertise with Python for Network Engineer and future-proof your networking career.
Enroll Now & Future‑Proof Your Career
Email: info@networkjourney.com
WhatsApp / Call: +91 97395 21088