Python parser script

We can now use a Python script to parse the LLDP neighbor output from each device and construct a network topology graph from it. The purpose is to automatically check the device to see whether any of the LLDP neighbors has disappeared due to link failure or other issues. Let's take a look at the cisco_graph_lldp.py file and see how that is done.

We start with the necessary imports of the packages--an empty list that we will populate with tuples of node relationships. We also know that Gi0/0 on the devices are connected to the management network; therefore, we are only searching for Gi0/[1234] as our regular expression pattern in the show LLDP neighbors output:

import glob, re
from graphviz import Digraph, Source
pattern = re.compile('Gi0/[1234]')
device_lldp_neighbors = []

We will use the glob.glob() method to traverse through the ./tmp directory of all the files, parse out the device name, and find the neighbors that the device is connected to. There are some embedded print statements in the script that were commented out; if you uncomment them, you will see that what we wanted to end up with was the parsed results:

device: r1
neighbors: r5-tor
neighbors: r6-edge
device: r5-tor
neighbors: r2
neighbors: r3
neighbors: r1
device: r2
neighbors: r5-tor
neighbors: r6-edge
device: r3
neighbors: r5-tor
neighbors: r6-edge
device: r6-edge
neighbors: r2
neighbors: r3
neighbors: r1

The fully populated edge list contains tuples that consist of the device and its neighbors:

Edges: [('r1', 'r5-tor'), ('r1', 'r6-edge'), ('r5-tor', 'r2'), ('r5-tor', 'r3'), ('r5-tor', 'r1'), ('r2', 'r5-tor'), ('r2', 'r6-edge'), ('r3', 'r5-tor'), ('r3', 'r6-edge'), ('r6-edge', 'r2'), ('r6-edge', 'r3'), ('r6-edge', 'r1')]

We can now construct the network topology graph using the Graphviz package. The most important part is the unpacking of the tuples that represent the edge relationship:

my_graph = Digraph("My_Network")
<skip>
# construct the edge relationships
for neighbors in device_lldp_neighbors:
node1, node2 = neighbors
my_graph.edge(node1, node2)

If you were to print out the resulting source dot file, it would be an accurate representation of your network:

digraph My_Network {
r1 -> "r5-tor"
r1 -> "r6-edge"
"r5-tor" -> r2
"r5-tor" -> r3
"r5-tor" -> r1
r2 -> "r5-tor"
r2 -> "r6-edge"
r3 -> "r5-tor"
r3 -> "r6-edge"
"r6-edge" -> r2
"r6-edge" -> r3
"r6-edge" -> r1
}

However, the placement of the nodes will be a bit funky, as it is autorendered. The following diagram illustrates the rendering in a default layout as well as the neato layout, namely digraph (My_Network, engine='neato'):

The neato layout represents an attempt to draw undirected graphs with even less hierarchy:

Sometimes the layout presented by the tool is just fine, especially if your goal is to detect faults as opposed to making it visually appealing. However, in this case, let's see how we can insert raw DOT language knobs into the source file. From research, we know that we can use the rank command to specify the level where some nodes can stay. However, there is no option presented in the Graphviz Python API. Luckily, the dot source file is just a string, which we can insert as raw dot comments using the replace() method with:

source = my_graph.source
original_text = "digraph My_Network {"
new_text = 'digraph My_Network {n{rank=same Client "r6-edge"}n{rank=same r1 r2 r3}n'
new_source = source.replace(original_text, new_text)
new_graph = Source(new_source)new_graph.render("output/chapter8_lldp_graph.gv")

The end result is a new source that we can render the final topology graph from:

digraph My_Network {
{rank=same Client "r6-edge"}
{rank=same r1 r2 r3}
Client -> "r6-edge"
"r5-tor" -> Server
r1 -> "r5-tor"
r1 -> "r6-edge"
"r5-tor" -> r2
"r5-tor" -> r3
"r5-tor" -> r1
r2 -> "r5-tor"
r2 -> "r6-edge"
r3 -> "r5-tor"
r3 -> "r6-edge"
"r6-edge" -> r2
"r6-edge" -> r3
"r6-edge" -> r1
}

The graph is now good to go:

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.131.10