cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
4384
Views
0
Helpful
10
Replies

I am looking to use python to connect to my ios devices to export the MAC table

Steven King
Level 1
Level 1

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? 

1 Accepted Solution

Accepted Solutions

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()



View solution in original post

10 Replies 10

WGL_BK
Level 1
Level 1

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 

Netmiko Library By Kirk Byers

 Github - Netmiko 

 

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.

thank you for your reply

 

so I got this from another post but when I run it I get some errors 

 

import pandas as pd
from netmiko import Netmiko
from getpass import getpass

password = getpass()
net_connect = Netmiko(host='192.168.1.1'username='username'password=password, device_type='cisco_ios')
mac_table = net_connect.send_command("show mac address-able"use_textfsm=True)
mac_data = {'mac':  [entry['mac'for entry in mac_table],
            'interface': [entry['ports'for entry in mac_table],
            'vlan': [entry['vlan'for entry in mac_table]
            }

df = pd.DataFrame(mac_data, columns=list(mac_data.keys()))

writer = pd.ExcelWriter('mac_table.xlsx'engine='xlsxwriter')
df.to_excel(writer, 'Sheet1')
writer.save()
 
------------------------------------------------------------
here are the errors anyone have any ideas 
 
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
 

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()



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

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 

 

Claudia de Luna
Spotlight
Spotlight

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()

 

thank you for your reply Claudia right now this is just for tracking to make sure no one is moving newly deployed phones. 

 

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

that is also great.  

Getting Started

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: