[DAY#4 PyATS Series] Creating Your First testbed.yaml (Multi-Vendor Testbed) in pyATS (Vendor-Agnostic) – Cisco/Arista/Palo Alto/Fortigate [Python for Network Engineer]

[DAY#4 PyATS Series] Creating Your First testbed.yaml (Multi-Vendor Testbed) in pyATS (Vendor-Agnostic) – Cisco/Arista/Palo Alto/Fortigate [Python for Network Engineer]

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 TestingVendor-Agnostic Testing (pyATS)
CLI commands differ per vendorAbstracted to a common model
Troubleshooting is manualScripted with automation
No centralized validationUnified, reusable tests
Not scalableEasily 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:

DeviceHostnameProtocolIP AddressUsernamePassword
Cisco RouterR1SSH192.168.1.1admincisco123
Arista SwitchSW1SSH192.168.1.2adminarista123
Palo Alto FWPA1SSH192.168.1.3adminpalo123
Fortigate FWFG1SSH192.168.1.4adminforti123

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:

FieldMeaning
devicesRoot container for all network devices
R1Hostname/alias of the device
osOperating system type: iosxe/arista/panos/fortinet
typeDevice type (router, switch, firewall)
credentialsLogin details for SSH or console access
connectionsDefines how pyATS connects to the device
protocolSSH/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:

VendorOS Value
Cisco IOS XEiosxe
Cisco NX-OSnxos
Cisco IOS XRiosxr
Arista EOSeos
Palo Alto PAN-OSpanos
Fortinet FortiOSfortinet

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:

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 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
Emailinfo@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!