09-29-2020 08:40 AM
hello I am new to programming and would like to use python to connect to my ios devices and export the MAC table to and excel spread sheet. I have about 60 devices that I would like to get the data from. I was wondering if anyone had anything like that or if anyone would give me some pointers on what to use to accomplish the task?
Solved! Go to Solution.
09-29-2020 12:23 PM
typo in this line table is missing the t
mac_table = net_connect.send_command("show mac address-able", use_textfsm=True
should be
mac_table = net_connect.send_command("show mac address-table", use_textfsm=True
That will fix the issue you are seeing but you may get errors on the keys. I am when I run it against a 3850.
If you want to use Pandas (which I totally recommend) might be good to run this in a Jupiter notebook so you an see what you are getting back from Netmiko and TextFSM.
That looks like a fairly old example using older Pandas.
Here is what worked for me:
import argparse import pandas as pd import netmiko import os import json from getpass import getpass def main(): os.environ["NET_TEXTFSM"] = "./ntc-templates/templates" password = getpass() net_connect = netmiko.Netmiko(host='10.1.10.216', username='cisco', password=password, device_type='cisco_ios') mac_table = net_connect.send_command("show mac address-table", use_textfsm=True) print(mac_table) print(len(mac_table)) for line in mac_table: print(json.dumps(line, indent=4)) mac_data = {'mac': [entry['destination_address'] for entry in mac_table], 'interface': [entry['destination_port'] for entry in mac_table], 'vlan': [entry['vlan'] for entry in mac_table] } df = pd.DataFrame(mac_data, columns=list(mac_data.keys())) print(df.head()) df.to_excel('mac_table.xlsx') # Standard call to the main() function. if __name__ == '__main__': parser = argparse.ArgumentParser(description="Script Description", epilog="Usage: ' python ccom' ") arguments = parser.parse_args() main()
09-29-2020 08:59 AM
Hi, Steven. You may want to try Paramiko/Netmiko as a start to make SSH connections to each device automatically. Once connected Netmiko allows you send either show commands or configuration command.
Here are a couple links that can get you started:
GNS3 Talks: Python for Network Engineers with GNS3 (Part 12) - Netmiko, SSH, Python and Cisco
There are other more in-depth methods like Ansible and Nornir but those need some time to appreciate, I think, plus I'm still learning those.
Good luck.
09-29-2020 10:28 AM
thank you for your reply
so I got this from another post but when I run it I get some errors
09-29-2020 12:23 PM
typo in this line table is missing the t
mac_table = net_connect.send_command("show mac address-able", use_textfsm=True
should be
mac_table = net_connect.send_command("show mac address-table", use_textfsm=True
That will fix the issue you are seeing but you may get errors on the keys. I am when I run it against a 3850.
If you want to use Pandas (which I totally recommend) might be good to run this in a Jupiter notebook so you an see what you are getting back from Netmiko and TextFSM.
That looks like a fairly old example using older Pandas.
Here is what worked for me:
import argparse import pandas as pd import netmiko import os import json from getpass import getpass def main(): os.environ["NET_TEXTFSM"] = "./ntc-templates/templates" password = getpass() net_connect = netmiko.Netmiko(host='10.1.10.216', username='cisco', password=password, device_type='cisco_ios') mac_table = net_connect.send_command("show mac address-table", use_textfsm=True) print(mac_table) print(len(mac_table)) for line in mac_table: print(json.dumps(line, indent=4)) mac_data = {'mac': [entry['destination_address'] for entry in mac_table], 'interface': [entry['destination_port'] for entry in mac_table], 'vlan': [entry['vlan'] for entry in mac_table] } df = pd.DataFrame(mac_data, columns=list(mac_data.keys())) print(df.head()) df.to_excel('mac_table.xlsx') # Standard call to the main() function. if __name__ == '__main__': parser = argparse.ArgumentParser(description="Script Description", epilog="Usage: ' python ccom' ") arguments = parser.parse_args() main()
10-20-2022 10:49 PM
Hi ,
How did you fix this - I am also getting the same error :
Traceback (most recent call last):
File "c:/testMac.py", line 8, in <module>
mac_data = {'mac': [entry['mac'] for entry in mac_table],
File "c:/testMac.py", line 8, in <listcomp>
mac_data = {'mac': [entry['mac'] for entry in mac_table],
TypeError: string indices must be integers
10-25-2022 08:47 AM
I had a typo missing a T int show mac address-table.
Also some times with difrent ios versions you have to change some of the entry's that you are looking for.
Hope that helps
09-29-2020 10:28 AM
Hi @Steven King,
If you are already somewhat comfortable with python then Netmiko with TextFSM integration is a good start. If you want to get started with describing a topology then Nornir (which will use Netmiko under the good) is a very good way to go. Honestly, if I were doing this today I'd look at pyATS.
I can describe my topology (including links)
Lots of parsers available (not just Cisco)
You can use Python or there is an interactive shell.
Best of all you get back structured data. You can easily put that into Excel if you like but over time I think you will find saving the data in formats that your scripts can use will save you lots of work. Trust me I know, I have tons of script to parse and save to Excel and then read from Excel. You can skip all of that!
Here is an example of Nornir and pyATS (pyATS for the parsing)
https://github.com/cldeluna/pyATS_Community_Solutions/tree/master/nornir_solutions
DevNet has lots of good info on getting started with pyATS.
If you want to go the Netmiko route, ping me and I'll dig up some examples.
Testbed file:
--- testbed: name: Underwater_Corporation_Testbed devices: mgmt-sw05: type: 'switch' os: 'iosxe' alias: 'Rack Management Switch' credentials: default: username: cisco password: cisco enable: password: cisco connections: cli: protocol: telnet ip: 10.1.10.102
Script:
from genie.testbed import load import json def main(): """ This is a Basic pyATS script to parse a show command. Interactive pyATS Shell: (pyats) claudia@Claudias-iMac pyats_intro % pyats parse "show mac address-table" --testbed-file uwaco_testbed.yml -output TEST :return: """ # Instantiate the Testbed # testbed = load('devnet_sbx_testbed.yml') testbed = load('uwaco_testbed.yml') print(f"\n======= TESTBED INFO =======\n") print(f"\tTestbed Value (object): {testbed}") print(f"\n======= END TESTBED INFO =======\n") # Sandbox NXOS Device # CLI: genie parse "show version" --testbed-file "devnet_sbx_testbed.yml" --devices "sbx-n9kv-ao" # This CLI command outputs the results into a directory called "out1" which does not have to exist # CLI & SAVE: genie parse "show version" --testbed-file "devnet_sbx_testbed.yml" --devices "sbx-n9kv-ao" --output PRE # DIFF CLI: genie diff PRE POST device = testbed.devices['mgmt-sw05'] # print(dir(device)) device.connect() response = device.parse('show mac address-table') print(f"\n====== Response from {device.name} is of type {type(response)} and length {len(response)}") print(response) print(f"\nFormatted JSON...") print(json.dumps(response, indent=4)) print(response.keys()) # Standard call to the main() function. if __name__ == '__main__': main()
09-29-2020 11:03 AM
thank you for your reply Claudia right now this is just for tracking to make sure no one is moving newly deployed phones.
09-29-2020 12:57 PM
I have similar scripts to help ensure all Macs come back after an upgrade or switch swap out.
pyATS is perfect for what you are trying to do.
(pyats) claudia@Claudias-iMac pyats_intro % pyats parse "show mac address-table" --testbed-file uwaco_testbed.yml --output PRE 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.73it/s] +==============================================================================+ | Genie Parse Summary for mgmt-sw05 | +==============================================================================+ | Connected to mgmt-sw05 | | - Log: PRE/connection_mgmt-sw05.txt | |------------------------------------------------------------------------------| | Parsed command 'show mac address-table' | | - Parsed structure: PRE/mgmt-sw05_show-mac-address-table_parsed.txt | | - Device Console: PRE/mgmt-sw05_show-mac-address-table_console.txt | |------------------------------------------------------------------------------| (pyats) claudia@Claudias-iMac pyats_intro % pyats parse "show mac address-table" --testbed-file uwaco_testbed.yml --output POST 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 1.56it/s] +==============================================================================+ | Genie Parse Summary for mgmt-sw05 | +==============================================================================+ | Connected to mgmt-sw05 | | - Log: POST/connection_mgmt-sw05.txt | |------------------------------------------------------------------------------| | Parsed command 'show mac address-table' | | - Parsed structure: POST/mgmt-sw05_show-mac-address-table_parsed.txt | | - Device Console: POST/mgmt-sw05_show-mac-address-table_console.txt | |------------------------------------------------------------------------------| (pyats) claudia@Claudias-iMac pyats_intro % pyats diff PRE POST 1it [00:00, 531.66it/s] +==============================================================================+ | Genie Diff Summary between directories PRE/ and POST/ | +==============================================================================+ | File: mgmt-sw05_show-mac-address-table_parsed.txt | | - Diff can be found at ./diff_mgmt-sw05_show-mac-address-table_parsed.txt | |------------------------------------------------------------------------------| (pyats) claudia@Claudias-iMac pyats_intro %
If we look at the diff file you can see
--- PRE/mgmt-sw05_show-mac-address-table_parsed.txt +++ POST/mgmt-sw05_show-mac-address-table_parsed.txt mac_table: vlans: 1: mac_addresses: - 000b.7866.79f7: - interfaces: - FastEthernet1/0/1: - entry_type: dynamic - interface: FastEthernet1/0/1 - mac_address: 000b.7866.79f7 - 0011.3228.d79b: - interfaces: - GigabitEthernet1/0/4: - entry_type: dynamic - interface: GigabitEthernet1/0/4 - mac_address: 0011.3228.d79b + 0011.93ed.b349: + interfaces: + FastEthernet1/0/24: + entry_type: dynamic + interface: FastEthernet1/0/24 + mac_address: 0011.93ed.b349 - 2c33.61ec.bbe6: - interfaces: - GigabitEthernet1/0/4: - entry_type: dynamic - interface: GigabitEthernet1/0/4 - mac_address: 2c33.61ec.bbe6 + f029.295c.cd18: + interfaces: + FastEthernet1/0/47: + entry_type: dynamic + interface: FastEthernet1/0/47 + mac_address: f029.295c.cd18 -total_mac_addresses: 33 +total_mac_addresses: 32
09-29-2020 01:46 PM
that is also great.
03-27-2021 11:36 AM
Find answers to your questions by entering keywords or phrases in the Search bar above. New here? Use these resources to familiarize yourself with the community: