pyATS and Genie Tutorial: Parse Show Commands and Test State - 夜莺博客

pyATS and Genie Tutorial: Parse Show Commands and Test State

Grep and eyeballs do not scale to a thousand devices, and regex parses break every time a vendor adds a column. pyATS with the Genie library solves that by shipping vendor-aware parsers that turn show interfaces output into Python dictionaries, plus a "learn" feature that snapshots protocol state and diffs it against a baseline later. This guide covers installation, the testbed file, parsing from Python and the CLI, building your own parsers, and how to wire a state-diff check into a pipeline so it fails loudly when the network changes underneath you.

Install and build a testbed

python3 -m venv ~/pyats-env && source ~/pyats-env/bin/activate
pip install pyats genie

genie create testbed interactive --output testbed.yml
pyats validate testbed testbed.yml

The testbed is a YAML description of your devices - credentials, OS, connection type and topology. Validate it before anything else: a testbed typo produces a confusing parser error rather than a connection error.

Parse show command output

from genie.testbed import load

testbed = load('testbed.yml')
dev = testbed.devices['core-sw1']
dev.connect(log_stdout=False)

parsed = dev.parse('show interfaces')
for name, i in parsed.items():
    print(name, i['oper_status'], i.get('counters', {}).get('in_crc_errors'))

# one-liner from the shell
# pyats parse "show ip route" --testbed-file testbed.yml --device core-sw1

The returned structure is a nested dictionary you can index directly - no regex, no fragile column offsets. The same parser handles IOS, IOS XE, IOS XR, NX-OS and Junos, so the same script works across platforms when you key on the fields you care about.

Learn state and diff against a baseline

# capture a snapshot
genie learn ospf --testbed-file testbed.yml --output baseline/

# ... hours later, after a change window ...
genie learn ospf --testbed-file testbed.yml --output after/

# compare
pyats diff baseline/ after/

This is the most valuable three-command workflow in the toolkit: it tells you exactly what changed in OSPF, BGP, interfaces, LLDP or spanning tree. Run genie learn all for a full snapshot, then diff after every maintenance window - it catches the neighbour-adjacency and route changes a human reviewer misses.

Write assertions, not reports

from genie.testbed import load
from pyats.aetest import Testcase, test

class NetworkHealth(Testcase):
    @test
    def bgp_established(self):
        dev = load('testbed.yml').devices['core-r1']
        dev.connect(log_stdout=False)
        bgp = dev.parse('show bgp summary')
        for peer, data in bgp['vrf']['default']['neighbor'].items():
            state = data['state']
            self.assertEqual(state, 'established', f'{peer} is {state}')
        dev.disconnect()

Save and run it with pyats run job or pyats run genie, and emit --json-report output that your CI system or orchestrator can consume. Because this is a test framework rather than a script collection, failures are first-class results with exit codes.

Custom parsers for anything missing

pyats shell --testbed-file testbed.yml
from genie.libs.parser.utils import get_parser_help
get_parser_help('show interfaces')

# structured output uses an XML control file per platform
# genie/libs/parser/iosxe/show_interface.py + show_interface.xml

Inspect an existing parser before writing one - nine times out of ten the command you need already exists, sometimes under a different platform directory. When you must extend, keep the parser's schema stable so downstream consumers do not break.

Where pyATS fits beside your other tools

pyATS is strongest for validation after change, Netmiko for straight-line CLI execution, NAPALM for getters and config diff at the API layer, and Ansible for orchestration and templating. Layering them - Ansible to push, pyATS to prove, Oxidized to archive - gives you change control with evidence. See also: Netmiko automation, NAPALM getters, Oxidized config backup and model-driven APIs compared.

原文链接:https://developer.cisco.com/docs/pyats/parsing-device-output