[Day #25 PyATS Series] OSPF Adjacency Validation Across Cisco/Arista/Palo Alto/Fortigate Using pyATS [Python for Network Engineer]

[Day #25 PyATS Series] OSPF Adjacency Validation Across Cisco/Arista/Palo Alto/Fortigate Using pyATS [Python for Network Engineer]

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:

  1. Connect to each device
  2. Run OSPF neighbor commands per vendor
  3. Parse adjacency state (Full, 2-Way, Down)
  4. 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:

Master Python Network Automation, Ansible, REST API & Cisco DevNet
Master Python Network Automation, Ansible, REST API & Cisco DevNet
Master Python Network Automation, Ansible, REST API & Cisco DevNet
Why Robot Framework for Network Automation?

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
Emailinfo@networkjourney.com
WhatsApp / Call: +91 97395 21088