Skip to content

Commit d843ee1

Browse files
committed
Initial release
0 parents  commit d843ee1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+1582
-0
lines changed

Diff for: .gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# python virtualenv
2+
env
3+
4+
# Generated files
5+
*.pyc
6+
7+
# Local inventory file
8+
inventory

Diff for: .gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "lib/ntc-ansible"]
2+
path = lib/ntc-ansible
3+
url = https://github.com/networktocode/ntc-ansible.git

Diff for: CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
= v0.1 - 2017-12-14
2+
3+
* Initial release
4+

Diff for: README.md

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# ansible-multicast-graph
2+
3+
Visualises the multicast trees for a single IPv4 group address using information
4+
scraped from NX-OS, EOS and IOS devices using ansible, ntc-ansible and TextFSM.
5+
6+
It is capable of showing the following information (provided all relevant
7+
devices are queried):
8+
9+
* The Rendezvouz Point device
10+
* What every other device believes the RP to be (to help detect config mismatches)
11+
* The direction of traffic flow on the shared multicast tree
12+
* The direction of traffic flow on any source-specific multicast trees
13+
* The publishes (IP addresses and name as discovered through LLDP)
14+
* The subscribers (as discovered through IGMP Snooping and LLDP)
15+
16+
![An example report](example.png)
17+
18+
This tool is very young and could be significantly improved upon.
19+
It was a first attempt at doing something useful while studying for Ivan Pepelnjak's
20+
[Building Network Automation Solutions](http://www.ipspace.net/Building_Network_Automation_Solutions)
21+
course.
22+
23+
## Quick start
24+
25+
* Clone this repository
26+
* Initialise the ntc-ansible submodule:
27+
28+
```bash
29+
git submodule update --init --recursive
30+
```
31+
32+
* Create a python virtualenv and install the dependencies:
33+
34+
```bash
35+
virtualenv env
36+
source env/bin/activate
37+
pip install -r requirements.txt
38+
```
39+
40+
* Update the `hosts` inventory file with your own devices
41+
* Create a vault file at `secrets/vault.yml` if you need ssh username and password
42+
to access your devices, otherwise just create an empty file there:
43+
44+
```bash
45+
ansible-vault create secrets/vault.yml
46+
# or
47+
touch secrets/vault.yml
48+
```
49+
50+
* Run the tool for your chosen multicast group with:
51+
52+
```bash
53+
ansible-playbook check_group.yml --extra-vars "mcast_group=224.0.0.123"
54+
```
55+
56+
The rendered graph will be written to the `outputs` directory with the group
57+
address as the filename and a .`.png` extension, e.g. `outputs/224.0.0.123.png`.
58+
59+
If you need to use a bastion host to connect to your network devices, uncomment the
60+
line in `hosts` file, and change the hostname of the bastion host there. Also edit
61+
`ssh_config` and set the right hostname there.
62+
63+
## Dependencies
64+
65+
* python (tested with 2.7 only)
66+
* ansible (tested with 2.3)
67+
* graphviz
68+
69+
This tool depends on several python libraries which are listed in the
70+
`requirements.txt` file, which is intended to be used with a python virtualenv.
71+
72+
## How it works
73+
74+
The playbook has several stages (each of which is tagged and can be run separately):
75+
76+
* `setup` - Creates the output directories
77+
* `fetch` - Fetches information from each device and writes them to separate output
78+
files. This stage is split into mutiple sub-stages, each of which are written to
79+
separate fiels.
80+
** `fetch-interfaces` - Retrieves list of interfaces
81+
** `fetch-lags` - Retrieves the list of link-aggregation groups
82+
** `fetch-neighbours` - Retrieves the list of LLDP neighbours
83+
** `fetch-rp` - Retrieves the Rendezvouz Point
84+
** `fetch-mroutes` - Retrieves the list of mroutes
85+
** `fetch-snooping` - Retrieves the list of IGMP subscribers
86+
* `compile` - Merges the separate output files into a single report for easier
87+
processing
88+
* `generate` - Generates the dot graph from the compiled report
89+
* `render` - Renders the output `png` image from the dot graph
90+
91+
The data is scraped from the devices using `ntc-ansible` and `ntc-templates`.
92+
This tool ships its own modified copy of several of the TextFSM templates shipped
93+
by ntc-templates which did not retrieve all of the necessary data. I intend to
94+
upstream those modifications when time permits.
95+
96+
All of the business logic for calculating the list of devices and relationships
97+
in the dot graph is done (ab)using jinja2 filters.
98+
99+
## Contributions
100+
101+
Pull requests are very much welcome!
102+

Diff for: ansible.cfg

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[defaults]
2+
transport=paramiko
3+
hostfile=./hosts
4+
host_key_checking=False
5+
timeout=5
6+
retry_files_enabled = False
7+
8+
library = env/lib/python2.7/site-packages/napalm_ansible/:lib/ntc-ansible/library
9+
#stdout_callback = selective
10+
callback_whitelist = profile_tasks

Diff for: check_group.yml

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
- name: Collate multicast details
3+
hosts: all
4+
connection: local
5+
gather_facts: false
6+
vars_files:
7+
- "{{vault_file|default('./secrets/vault.yml')}}"
8+
- "{{inventory_dir}}/vars/ntc.yml"
9+
vars:
10+
mcast_group: "UNSET"
11+
mcast_net: "224.0.0.0/4"
12+
results: "{{inventory_dir}}/outputs"
13+
host_results: "{{ results }}/{{ inventory_hostname }}"
14+
task_list:
15+
- "tasks/{{os}}/{{task_path|basename}}"
16+
- "{{task_path}}"
17+
18+
tasks:
19+
- name: Validate multicast group address
20+
fail:
21+
msg: "Valid multicast group must be passed to playbook with -e/--extra-vars, e.g. `-e mcast_group=224.0.0.1`"
22+
when: not mcast_group|ipaddr or not mcast_group|ipaddr(mcast_net)
23+
24+
- name: Create output directories
25+
local_action: file path={{ results }} state=directory
26+
run_once: true
27+
tags: ['setup']
28+
29+
- name: Create host output directories
30+
local_action: file path={{ host_results }} state=directory
31+
tags: ['setup']
32+
33+
- name: "Include tasks"
34+
include: "{{ lookup('first_found', task_list) }}"
35+
with_fileglob: [ "tasks/*.yml" ]
36+
loop_control:
37+
loop_var: task_path
38+
39+
- name: "Compile Report"
40+
template:
41+
src: "templates/report.j2"
42+
dest: "{{results}}/{{mcast_group}}.yaml"
43+
run_once: true
44+
tags: ['compile']
45+
46+
- name: "Generate Graph"
47+
template:
48+
src: "templates/graph.j2"
49+
dest: "{{results}}/{{mcast_group}}.dot"
50+
vars:
51+
report: "{{ lookup('file', results + '/' + mcast_group + '.yaml')|from_yaml }}"
52+
edges: "{{ report|get_mroute_edges(mcast_group, play_hosts) }}"
53+
run_once: true
54+
tags: ['generate']
55+
56+
- name: "Render Graph"
57+
command: dot -Tpng "{{results}}/{{mcast_group}}.dot" -o "{{results}}/{{mcast_group}}.png"
58+
run_once: true
59+
tags: ['render']
60+
61+
62+
63+
# vim: set ts=2 shiftwidth=2 expandtab :

Diff for: example.png

415 KB
Loading

Diff for: filter_plugins/indent.py

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class FilterModule(object):
2+
3+
def indent_block(self, value, indent=2):
4+
return "\n".join([' '*indent + l for l in value.splitlines()])
5+
6+
def filters(self):
7+
return {
8+
'indent_block': self.indent_block,
9+
}

0 commit comments

Comments
 (0)