Write a Python script

As a network engineer or programmer, you can write your own Python scripts that use the pyATS libraries to automate your network testing. A script is simply a Python file that lists different actions and lets you run them with a single command. In pyATS terms, a script is an aggregation of Triggers and Verifications.

This topic describes how to write a basic script and how to add complexity to that script.

Attention

Before you run the example scripts provided in this section, make sure you have the latest pyATS Library packages, version 19.10 or higher:

pip install pyats[library] --upgrade

Why write a script?

Automation means that you can programmatically establish connections to your devices and perform operations on them. Scripts automate your network operations — you simply define a list of commands once and then reuse the script as often as required, on-demand or at scheduled intervals.

For example, let’s say that you have a device with over 100 interfaces, and that you need to monitor these daily to make sure they are up. You could, of course, manually execute a show command and then read through hundreds of lines of code to find the state of each interface. This is time consuming, however, and introduces the possibility of human error, which could adversely affect the state of your network.

The pyATS Library provides a better solution!

  • Write a script that automates the process using the pyATS Library functionality to connect, configure, and verify the device state.

  • Rerun the script as needed, either as a scheduled job or on demand.

Tip

Remember, the pyATS Library gives you structured output that makes reuse possible.

Write a basic script

This example shows you how to write and run a basic script to check the state of a device interface.

Note

This example uses pure Python. For information about how to use the pyATS Library command line interface, see the Get Started with pyATS Guide topic What is the pyATS Library CLI?.

Sample script - basic

We provide you with an example of a commented script that:

  • checks the status of a network interface

  • changes the configuration, and

  • re-checks the interface status.

We also provide you with pre-recorded output so that you can see the results. Download the first sample file, and then extract the files to a directory of your choice. Take a look at the testbed.yaml, and open simple_script1.py in a text editor to see additional log.info statements that make the on-screen output clear.

To run the script:

  1. In your Linux terminal, source the environment variables.

    • For Bash:

      source script1_env.sh
      
    • For C shell:

      source script1_env.csh
      
  2. Run the script:

    python simple_script1.py
    
  3. Clear the mock environment variable that you set in step 1.

    • For Bash:

      unset UNICON_REPLAY
      
    • For C shell:

      unsetenv UNICON_REPLAY
      

Steps to write a basic script

The following procedure describes the steps that you take to write the same sample script.

  1. Open a text editor and start a new .py file.

  2. Import the functionality that you need from Python, pyATS, and the pyATS Library. For a description of the more commonly used functionality that you might want to import, see the topic Useful Libraries.

    Remember that you always need to load the Testbed YAML file.

    # Python
    import sys
    import time
    import logging
    
    # Enable logger
    logging.basicConfig(stream=sys.stdout, level=logging.INFO, format='%(message)s')
    log = logging.getLogger(__name__)
    
    # Import functionality from the pyATS library
    from genie.testbed import load
    
  3. If you’d like your script to display formatted messages as it runs, you can use the banner functionality.

    from pyats.log.utils import banner
    
  4. You imported the load functionality in step 2, so now you can load the testbed file and display useful messages.

    log.info(banner("Loading testbed"))
    testbed = load('testbed.yaml')
    log.info("\nPASS: Successfully loaded testbed '{}'\n".format(testbed.name))
    
  5. Now connect to one of the devices in the testbed. In this example, nx-osv-1 is the hostname of a device in the Testbed YAML file.

    device = testbed.devices['nx-osv-1']
    device.connect(via='cli')
    
  6. Check the current state of the interface and parse the output into a data structure that has Key-value pairs. We expect that the interface Ethernet2/1 is currently down.

    pre_output = device.parse("show interface Ethernet2/1 brief")
    
  7. With the data parsed and stored as the Object pre_output, check the value of the status key.

    pre_status = pre_output['interface']['ethernet']['Ethernet2/1']['status']
    if pre_status == 'down':
        log.info("\nPASS: Interface Ethernet2/1 status is 'down' as expected\n")
    else:
        log.error("\nFAIL: Interface Ethernet2/1 status is not 'down' as expected\n")
    exit()
    
  8. Bring the interface up using the Conf module.

    device.configure("interface Ethernet2/1\n"
               " no shutdown")
    
  9. Use sleep to give the configuration time to take effect.

    time.sleep(15)
    
  10. Re-check the interface state – parse the output and store it in the post_output object.

    post_output = device.parse("show interface Ethernet2/1 brief")
    
  11. Verify that the interface is now up.

    post_status = post_output['interface']['ethernet']['Ethernet2/1']['status']
    if post_status == 'up':
        log.info("\nPASS: Interface Ethernet2/1 status is 'up' as expected\n")
    else:
        log.error("\nPASS: Interface Ethernet2/1 status is not 'up' as expected\n")
    
  12. Save the file as myscript1.py.

And there you have it!

Note

You can add a Python debugger to your code at any point that you want to stop and debug:

import pdb; pdb.set_trace()

Write an advanced script

Sample script - advanced

We provide you with an example of a commented script that

  • connects to two devices

  • gets the number of established BGP neighbors on the first device

  • learns the BGP feature on the first device

  • shuts down the BGP neighbor on the first device

  • learns the BGP feature again after the configuration change

  • uses the pyATS Library Diff functionality to verify that the BGP neighbor is down

  • restores the BGP neighbor

  • learns the BGP feature again after the second configuration change

  • uses the pyATS Library Diff functionality to verify that there are minimal differences in the device operational state

  • verifies the number of BGP neighbors on the first device, and

  • checks the interface status of all interfaces on the device.

We also provide you with pre-recorded output so that you can see the results. Download the second sample file, and then extract the files to a directory of your choice. In a text editor, open and read through the testbed.yaml and simple_script2.py files.

To run the script:

  1. In your Linux terminal, source the environment variables.

    • For Bash:

      source script2_env.sh
      
    • For C shell:

      source script2_env.csh
      
  2. Run the script:

    python simple_script2.py
    
  3. Clear the mock environment variable that you set in step 1.

    • For Bash:

      unset UNICON_REPLAY
      
    • For C shell:

      unsetenv UNICON_REPLAY
      

Steps to write an advanced script

Open the file simple_script2.py, and note the following differences from the basic script.

  1. This example imports additional functionality so that you can use Diff and an API that gets BGP information:

    from genie.testbed import load
    from ats.log.utils import banner
    from genie.utils.diff import Diff
    from genie.libs.sdk.apis.iosxe.bgp.get import get_bgp_session_count
    
  2. This script uses the Ops module learn functionality to learn the BGP feature (issue and parse a series of show commands):

    pre_bgp_ops = dev_xe.learn("bgp")
    

    The script uses the learn functionality again later to learn the feature after configuration changes.

  3. The script uses an API function to get the number of established BGP neighbors:

    orig_bgp_estab_nbrs = dev_xe.api.get_bgp_session_count(in_state='established')
    
  4. Make a configuration change in the feature BGP, and then relearn the changes:

    dev_xe.configure("router bgp 65000\n"
                     " neighbor 10.2.2.2 shutdown")
    
  5. Diff compares the operational state of the device before and after configuration changes:

    log.info(banner("Use Genie Diff to verify BGP neighbor is shutdown on XE device '{}'".\
                format(dev_xe.name)))
    
    bgp_diff = Diff(pre_bgp_ops.info, post_bgp_ops1.info)
    bgp_diff.findDiff()
    log.info("Genie Diffs observed, BGP neighbor is shutdown/missing:\n\n" + str(bgp_diff) + "\n")
    
  6. Notice the “for” loop, which checks the status of all interfaces on the XE device:

    intf_output = dev_xe.parse('show ip interface brief')
    
    for interface in intf_output['interface']:
        status = intf_output['interface'][interface]['status']
        if status == 'up':
            log.info("\nPASS: Interface {intf} status is: '{s}'".format(intf=interface, s=status))
        elif status == 'down':
            log.error("\nFAIL: Interface {intf} status is: '{s}'".format(intf=interface, s=status))
    

Note

You can add a Python debugger to your code at any point that you want to stop and debug:

import pdb; pdb.set_trace()

See also…