We sure can build static dictionaries to interact with network devices for the purpose of network automation.
How to Automate Network Devices using Python Netmiko Part I
In the real world, this is not practical, we almost always will be required to read the device data from an inventory source which most of the time is going to be a csv file or an excel sheet. To demonstrate this, I am going to take Cisco Always ON Devnet Sandbox devices for example.
[FREE] Cisco Always on Devnet Sandbox Lab
I have converted the dictionary into a csv file that you can download for reference and the below screenshot has the directory structure that you need to set up for the python script.
Official Python CSV documentation can be found here
from netmiko import ConnectHandler
import csv
with open('cisco_always_on_devnet_sanbox_lab.csv', encoding='utf-8-sig') as f:
for row in csv.reader(f):
print(row)
╰─ python3 script2.py ─╯
['HOST', 'SSH PORT', 'NETCONF PORT', 'RESTCONF PORT', 'USERNAME', 'PASSWORD', 'SECRET']
['sandbox-iosxe-latest-1.cisco.com', '22', '830', '443', 'developer', 'C1sco12345', 'C1sco12345']
['sandbox-iosxe-recomm-1.cisco.com', '22', '830', '443', 'developer', 'C1sco12345', 'C1sco12345']
['sandbox-iosxr-1.cisco.com', '22', '830', '', 'admin', 'C1sco12345', 'C1sco12345']
['sandbox-nxos-1.cisco.com', '22', '830', '443', 'admin', 'Admin_1234!', 'Admin_1234!']
Now that we can read the data, we can build the data structure required by netmiko to interact with devices dynamically. A sample data structure that netmiko requires is
csr1000v1 = {
'device_type': 'cisco_xe',
'host': 'sandbox-iosxe-latest-1.cisco.com',
'username': 'developer',
'password': 'C1sco12345',
'port' : 22, # optional, defaults to 22
'secret': 'C1sco12345', # optional, defaults to ''
}
We are using pprint ( pretty print ) module to print the formatted output of the dictionary for easy reading
from netmiko import ConnectHandler
import csv
from pprint import pprint
device_list = []
with open('cisco_always_on_devnet_sanbox_lab.csv', encoding='utf-8-sig') as f:
for row in csv.reader(f):
device_dict = {
'host' : row[0],
'device_type' : row[1],
'username' : row[5],
'password' : row[6],
'secret' : row[7],
}
device_list.append(device_dict)
pprint(device_list)
─ python3 script2.py ─╯
[{'device_type': 'device_type',
'host': 'HOST',
'password': 'PASSWORD',
'secret': 'SECRET',
'username': 'USERNAME'},
{'device_type': 'cisco_xe',
'host': 'sandbox-iosxe-latest-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'developer'},
{'device_type': 'cisco_xe',
'host': 'sandbox-iosxe-recomm-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'developer'},
{'device_type': 'cisco_xr',
'host': 'sandbox-iosxr-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'admin'},
{'device_type': 'cisco_nxos',
'host': 'sandbox-nxos-1.cisco.com',
'password': 'Admin_1234!',
'secret': 'Admin_1234!',
'username': 'admin'}]
The problem here is, the first dictionary contains the header information of the csv sheet and there are multiple ways to get around this problem. We can either delete the first index of this list or we can use next() before we create dictionaries.
METHOD1:-
from netmiko import ConnectHandler
import csv
from pprint import pprint
device_list = []
with open('cisco_always_on_devnet_sanbox_lab.csv', encoding='utf-8-sig') as f:
next(f)
for row in csv.reader(f):
device_dict = {
'host' : row[0],
'device_type' : row[1],
'username' : row[5],
'password' : row[6],
'secret' : row[7],
}
device_list.append(device_dict)
pprint(device_list)
╰─ python3 script2.py ─╯
[{'device_type': 'cisco_xe',
'host': 'sandbox-iosxe-latest-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'developer'},
{'device_type': 'cisco_xe',
'host': 'sandbox-iosxe-recomm-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'developer'},
{'device_type': 'cisco_xr',
'host': 'sandbox-iosxr-1.cisco.com',
'password': 'C1sco12345',
'secret': 'C1sco12345',
'username': 'admin'},
{'device_type': 'cisco_nxos',
'host': 'sandbox-nxos-1.cisco.com',
'password': 'Admin_1234!',
'secret': 'Admin_1234!',
'username': 'admin'}]
METHOD2:-
Instead of using csvReader, we can leverage DictReader of csv module that will reader the header and the values in each row as a dictionary. Allows us to not manually having to handle the header line or use list index values but instead use header names to index.
from netmiko import ConnectHandler
import csv
from pprint import pprint
device_list = []
with open('cisco_always_on_devnet_sanbox_lab.csv', encoding='utf-8-sig') as f:
for row in csv.DictReader(f):
device_dict = {
'host' : row['HOST'],
'device_type' : row['device_type'],
'username' : row['USERNAME'],
'password' : row['PASSWORD'],
'secret' : row['SECRET'],
}
device_list.append(device_dict)
pprint(device_list)
Read more about how to write csv files using python for network automation
2 thoughts on “How to read write csv with python for Network Automation Part 1”