Table of Contents
Introduction: Your First Step into Vendor-Agnostic Automation
Welcome to another exciting post in our 101 Days of pyATS series! Today, we’re getting hands-on by creating your very first testbed.yaml
file. If you’re diving into network automation and testing, especially using Python for Network Engineers, this is where your journey gets real. We’ll walk through building a multi-vendor testbed—with Cisco, Arista, Palo Alto, and Fortigate devices—all in a single, unified YAML file.
If you’ve ever struggled with vendor-specific tools or clunky CLI scripts that don’t scale, then vendor-agnostic testing using Cisco pyATS is your holy grail. You’ll learn why it’s vital, how devices communicate in a lab environment, and how to convert that topology into a testbed your Python code can interact with directly.
Let’s gear up to automate smarter.
Topology Overview
In today’s post, we’ll be referring to the following virtual or lab topology:

This topology forms the basis of our YAML testbed. Each device will be represented in a vendor-agnostic way so that your automation workflows, irrespective of the vendor, stay consistent and scalable.
Why Vendor-Agnostic Testing Matters
Most network environments today are multi-vendor by nature. Whether due to acquisition, budget constraints, or functional requirements, network engineers are juggling Cisco, Juniper, Arista, Palo Alto, Fortigate, and more.
Here’s why vendor-agnostic testbeds like pyATS are essential:
Traditional Testing | Vendor-Agnostic Testing (pyATS) |
---|---|
CLI commands differ per vendor | Abstracted to a common model |
Troubleshooting is manual | Scripted with automation |
No centralized validation | Unified, reusable tests |
Not scalable | Easily scalable via Python APIs |
Benefits:
- One test suite to test multiple vendors.
- Automated testing before production rollout.
- Less human error.
- More confidence in every network change.
Topology & Communications – Under the Hood
Each device in our topology will be reachable via SSH or Telnet. Here’s a simplified communication matrix:
Device | Hostname | Protocol | IP Address | Username | Password |
---|---|---|---|---|---|
Cisco Router | R1 | SSH | 192.168.1.1 | admin | cisco123 |
Arista Switch | SW1 | SSH | 192.168.1.2 | admin | arista123 |
Palo Alto FW | PA1 | SSH | 192.168.1.3 | admin | palo123 |
Fortigate FW | FG1 | SSH | 192.168.1.4 | admin | forti123 |
Connectivity Tip: Make sure all devices are reachable via ping/SSH before loading them into your testbed.
pyATS Workflow Script
The pyATS workflow follows these simplified steps:
1. Define your testbed in a YAML file.
2. Load the testbed using pyATS.
3. Connect to each device programmatically.
4. Execute CLI or API commands.
5. Parse outputs and validate.
6. Generate reports.
We’ll focus today on Step 1—creating your testbed.yaml
.
Explanation by Line (What Each YAML Field Means)
Here’s what a typical device entry in the testbed.yaml
looks like:
devices:
R1:
os: iosxe
type: router
credentials:
default:
username: admin
password: cisco123
connections:
cli:
protocol: ssh
ip: 192.168.1.1
Key Fields Explained:
Field | Meaning |
---|---|
devices | Root container for all network devices |
R1 | Hostname/alias of the device |
os | Operating system type: iosxe/arista/panos/fortinet |
type | Device type (router, switch, firewall) |
credentials | Login details for SSH or console access |
connections | Defines how pyATS connects to the device |
protocol | SSH/Telnet/Console |
Repeat this for each vendor, adjusting os
, ip
, and credentials
accordingly.
Full Example: testbed.yaml
Here’s a complete testbed for our multi-vendor setup:
testbed:
name: MultiVendorLab
credentials:
default:
username: admin
password: admin123
devices:
R1:
os: iosxe
type: router
connections:
cli:
protocol: ssh
ip: 192.168.1.1
SW1:
os: eos
type: switch
connections:
cli:
protocol: ssh
ip: 192.168.1.2
PA1:
os: panos
type: firewall
connections:
cli:
protocol: ssh
ip: 192.168.1.3
port: 22
FG1:
os: fortinet
type: firewall
connections:
cli:
protocol: ssh
ip: 192.168.1.4
Multi-Vendor CLI Screenshots
Here’s a glimpse of what connection verification looks like:
Cisco:
(pyats) > python
>>> from genie.testbed import load
>>> testbed = load('testbed.yaml')
>>> device = testbed.devices['R1']
>>> device.connect()
Arista:
>>> device = testbed.devices['SW1']
>>> device.connect()
>>> device.execute("show version")
Palo Alto:
>>> device = testbed.devices['PA1']
>>> device.connect()
>>> device.execute("show system info")
Fortigate:
>>> device = testbed.devices['FG1']
>>> device.connect()
>>> device.execute("get system status")
FAQs
1: What is the purpose of the testbed.yaml
file in pyATS?
Answer:
The testbed.yaml
file serves as the central configuration file in pyATS to define all devices, their credentials, and how to connect to them. It’s vendor-agnostic and allows you to run scripts against Cisco, Arista, Fortigate, Palo Alto, or any other platform by abstracting connection logic from your Python code.
Instead of hardcoding IPs and credentials, you keep your scripts clean by loading this YAML dynamically using:
from genie.testbed import load testbed = load('testbed.yaml')
This makes your testing modular, scalable, and repeatable across different environments.
2: How can I validate if my testbed.yaml
file is correctly formatted?
Answer:
To ensure your YAML file is syntactically and structurally valid, use the built-in validation command:
pyats validate testbed testbed.yaml
This will:
- Check for schema compliance
- Catch missing keys (like
connections
) - Validate YAML indentation and data types
Validation before execution helps prevent runtime errors in your scripts.
3: Can I define multiple connection protocols (SSH, Telnet, Console) in the same testbed?
Answer:
Yes, pyATS supports multi-connection definitions per device. You can define multiple protocols under the connections:
section and choose which one to use when writing your script.
Example:
connections: ssh: protocol: ssh ip: 192.168.1.1 telnet: protocol: telnet ip: 192.168.1.1
Then, in your Python script, you can explicitly connect via one of them:
device.connect(via='telnet')
This is useful when certain vendors or lab environments only support telnet or console.
4: What should I do if a device fails to connect during script execution?
Answer:
If a device fails to connect (e.g., wrong IP, port down, SSH issue), pyATS will throw an exception like:
ConnectionError: Could not connect to device "R1"
You should wrap your device.connect()
call in a try-except block to handle it gracefully:
try: device.connect() except Exception as e: print(f"Connection to {device.name} failed: {e}")
Also, verify:
- Device reachability (ping/SSH)
- Correct protocol and port
- Credentials match
Adding logging for failures can help with troubleshooting large topologies.
5: How do I define device-specific credentials if defaults don’t apply to all?
Answer:
You can override the global default
credentials by setting device-level credentials:
testbed: credentials: default: username: admin password: admin123 devices: R1: credentials: default: username: cisco password: cisco123
This way:
R1
uses its own username/password.- All others fall back to the testbed-level default.
This is helpful in real environments where each vendor might have different login setups.
6: How do I handle non-standard SSH ports (e.g., 2222) in pyATS YAML?
Answer:
You can specify a custom port under the cli:
connection like this:
connections: cli: protocol: ssh ip: 192.168.1.10 port: 2222
In your script, this is transparent. When you call device.connect()
, pyATS will use the specified port automatically.
This is especially useful in NAT’d or shared-lab environments where SSH ports are mapped differently.
7: What are the common os:
values supported by pyATS?
Answer:
The os:
field helps pyATS decide how to parse command outputs correctly. Here are some common values:
Vendor | OS Value |
---|---|
Cisco IOS XE | iosxe |
Cisco NX-OS | nxos |
Cisco IOS XR | iosxr |
Arista EOS | eos |
Palo Alto PAN-OS | panos |
Fortinet FortiOS | fortinet |
Make sure to match this value with the correct parser/genie support for accurate parsing and validation.
8: Can I group devices into roles (routers, switches, firewalls) for easier scripting?
Answer:
While YAML doesn’t support grouping natively, you can use custom attributes like type:
or define device tags in your script to sort/group them:
devices: R1: type: router SW1: type: switch PA1: type: firewall
Then in Python:
for device in testbed.devices.values(): if device.type == 'firewall': firewall_list.append(device)
This makes it easier to apply role-based logic in your automation scripts.
9: Can pyATS connect to cloud-hosted virtual appliances?
Answer:
Yes, as long as:
- The appliance has reachable IP from your control node
- SSH is enabled and reachable
- Proper credentials and protocol are set in the YAML
You can automate vSRX, CSR1000v, Palo Alto VM-Series, etc., just like physical devices. pyATS is protocol-based, not hardware-bound.
10: How do I keep my testbed.yaml
file secure and avoid exposing credentials?
Answer:
Best practices for securing your testbed:
- Do not commit YAML files to Git with real passwords.
- Use
.gitignore
for sensitive testbed files. - Store credentials in environment variables or use pyATS Secrets Plugin.
- Encrypt YAML with Ansible Vault, GPG, or similar tools.
- Consider using a dynamic inventory generation tool (e.g., NetBox + script) that injects secrets at runtime.
Security is critical when automating production-grade networks.
Let me know if you’d like these exported in Markdown/HTML/WordPress block format or turned into a downloadable FAQ PDF for your course site or student handouts.
YouTube Link
Watch the Complete Python for Network Engineer: Creating Your First testbed.yaml (Multi-Vendor Testbed) in pyATS (Vendor-Agnostic) – Cisco/Arista/Palo Alto/Fortigate Lab Demo & Explanation on our channel:
Join Our Full Training
This post was just a glimpse of what’s possible with pyATS and vendor-agnostic automation.
Want to go deeper?
Trainer Sagar Dhawan is conducting a 3-month instructor-led program:
“Python + Ansible + API + Cisco DevNet for Network Engineers”
Explore full course: https://course.networkjourney.com/python-ansible-api-cisco-devnet-for-network-engineers/
Click below to view course outline and enroll:
Enroll Now & Future‑Proof Your Career
Email: info@networkjourney.com
WhatsApp / Call: +91 97395 21088
https://course.networkjourney.com/python-ansible-api-cisco-devnet-for-network-engineers
Whether you’re a beginner or a pro, this program will empower you to use Python for Network Engineers to automate real-world networks with confidence.
- Build testbeds
- Write automated tests
- Run CLI/API validations
- Handle multi-vendor environments
- Use REST APIs with Postman and Python
- Job-ready portfolio by Day 90!
Limited Seats – Register Now and Future-Proof Your Career!