Compare Network States

Once you know how to parse device output or learn device features, you can begin to unleash the power of the pyATS Library for stateful network validation!

This topic describes how to use the Diff functionality to monitor your network and to verify that your network is performing as expected.

The pyATS Library Diff functionality enables you to compare “snapshots” of your network so that you can easily see any changes. For any two Python dictionaries or objects with a consistent data structure (the set of key-value pairs), the system compares the keys and identifies differences. You can exclude keys that you don’t want to compare.

Tip

You don’t need to know Python – the Library CLI includes a Diff command that you can run in your Linux terminal.

How stateful validation works

Using the pyATS Library, you can collect and compare network state information on demand, or as scheduled jobs that run your automation scripts. The process is simple:

  1. Take a snapshot of your network.

  2. Make or observe a change in your network.

  3. Take another snapshot.

  4. Use Diff to see the changes.

For example, you can set up a scheduled job to take a new snapshot every day, to make sure your network is running as it should and to see any configuration changes. The result is a Linux-style list of additions, deletions, and changes.

Examples of stateful validation

The following examples show how you can monitor changes in configuration and state, using both learned and parsed output.

Remember that learn runs multiple show commands and creates a consistent output structure across devices. By contrast, parse typically parses the output of a single show command, with output structure that is consistent for each device but can vary across devices.

Tip

For a detailed example that includes automation, see the workshop DevNet-2595: Stateful Network Validation using pyATS+Genie and Robot Framework.

Compare learned snapshots

In this example, you’ll see how to take snapshots with the learn function, save the snapshots to different directories, and then compare the data.

Note

We’ll show you all of the actions and results, because mock data doesn’t work with this example. The workshop provides examples that you can try yourself.

  1. With your devices already configured and running, take a snapshot of the bgp feature and save it to the directory (or variable) output1. You can use a Python interpreter or the Library command line.

    • If you want to use Python, use pyats shell to load the testbed API and create your testbed and device objects. Then, tell the system to connect to each device and to learn the specified feature:

      (pyats) $ pyats shell --testbed-file mock.yaml
         >>> output1 = {}
         >>> for name, dev in testbed.devices.items():
         ...     dev.connect()
         ...     output1[name] = {}
         ...     output1[name]['bgp'] = dev.learn('bgp')
         ...
      

      This example uses a Python for loop to execute each statement on all devices in the testbed.

      Result: The system stores the feature information in a Python dictionary, which includes the data for all devices.

    • If you want to use the CLI:

      (pyats) $ pyats learn "bgp" --testbed-file mock.yaml --output output1
      

      Result: The system creates the output directory output1, stores the ops.txt device files in JSON format, and displays a summary for each device:

      +==============================================================================+
      | Genie Learn Summary for device nx-osv-1                                      |
      +==============================================================================+
      |  Connected to nx-osv-1                                                       |
      |  -   Log: output1/connection_nx-osv-1.txt                                    |
      |------------------------------------------------------------------------------|
      |  Learnt feature 'bgp'                                                        |
      |  -  Ops structure:  output1/bgp_nxos_nx-osv-1_ops.txt                        |
      |  -  Device Console: output1/bgp_nxos_nx-osv-1_console.txt                    |
      |==============================================================================|
      
      +==============================================================================+
      | Genie Learn Summary for device csr1000v-1                                    |
      +==============================================================================+
      |  Connected to csr1000v-1                                                     |
      |  -   Log: output2/connection_csr1000v-1.txt                                  |
      |------------------------------------------------------------------------------|
      |  Learnt feature 'bgp'                                                        |
      |  -  Ops structure:  output2/bgp_iosxe_csr1000v-1_ops.txt                     |
      |  -  Device Console: output2/bgp_iosxe_csr1000v-1_console.txt                 |
      |==============================================================================|
      
  2. Change the configuration of a feature on a device, or shut down/bring up an interface.

  3. Repeat step 1 to take another snapshot, but specify a different output directory or variable, such as output2.

  4. Compare the two snapshots:

    • Python:

      >>> from genie.utils.diff import Diff
      >>> diff = Diff(output1.info, output2.info)
      >>> diff.findDiff()
      >>> print(diff)
      

    Tip

    Refer to Genie Python Diff.

    • pyATS Library CLI:

      $ (pyats) genie diff output1 output2
      

    Result: The system displays any differences.

    Tip

    Refer to Genie CLI Diff.

    Note

    + indicates an addition, - indicates a deletion, and + followed by - indicates a change.

    more output/diff_bgp_nxos_nxos-osv-1_ops.txt
    --- output1/bgp_nxos_nxos-osv-1_ops.txt
    +++ output2/bgp_nxos_nxos-osv-1_ops.txt
    info:
    instance:
    default:
    vrf:
        default:
        neighbor:
        50.1.1.101:
        address_family:
            ipv4 multicast:
    +         session_state: active
    -         session_state: idle
            ipv4 unicast:
    +         session_state: active
    -         session_state: idle
    

    In this example, you can see that ipv4 multicast and ipv4 unicast both changed from idle to active.

Compare parsed snapshots

In this example, you can see how to parse the output of a single show command at two different points in time, and then use Diff to compare the output.

Tip

Because the parsed output structure can vary across devices, this example shows you how to take a snapshot on a single device. You can, of course, write a script that automates this process for every device in your network.

  1. With your device already configured and running, take a snapshot and save it to the directory (or variable) po1. You can use a Python interpreter or the Library command line.

    • If you want to use Python, use pyats shell to load the testbed API and create your testbed and device objects. Then, tell the system to connect to a device and parse the specified command:

      (pyats) $ pyats shell --testbed-file tb.yaml
         >>> dev = testbed.devices['uut']
         >>> dev.connect()
         >>> po1 = dev.parse('show ip ospf interface brief')
      

      Result: The system stores the parsed output in a Python dictionary.

    • If you want to use the CLI:

      (pyats) $ pyats parse "show ip ospf interface brief" --testbed-file tb.yaml --devices uut --output po1
      

      Result: The system creates the output directory po1, stores the parsed.txt file in JSON format, and displays a summary for the device:

      +==============================================================================+
      | Genie Parse Summary for nx-osv-1                                             |
      +==============================================================================+
      |  Connected to nx-osv-1                                                       |
      |  -  Log: po1/connection_nx-osv-1.txt                                         |
      |------------------------------------------------------------------------------|
      |  Parsed command 'show ip ospf interface brief'                               |
      |  -  Parsed structure: po1/nx-osv-1_show-ip-ospf-interface-brief_parsed.txt   |
      |  -  Device Console:   po1/nx-osv-1_show-ip-ospf-interface-brief_console.txt  |
      |------------------------------------------------------------------------------|
      
  2. Shut down an interface.

  3. Repeat step 1 to take another snapshot, but specify a different output directory or variable, such as po2.

  4. Compare the two snapshots:

    • Python:

    >>> from genie.utils.diff import Diff
    >>> diff = Diff(po1, po2)
    >>> diff.findDiff()
    >>> print(diff)
    
    • pyATS Library CLI:

      $ (pyats) genie diff po1 po2
      

    Result: The system displays any differences.

     GigabitEthernet2:
    +      nbrs_count: 0
    -      nbrs_count: 1
    +      nbrs_full: 0
    -      nbrs_full: 1
    +      state: DOWN
    -      state: P2P
    

    You can see in this example that GigabitEthernet2 is now down.

See also…