-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
514 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
''' | ||
This is a solution to the below problem given the content we have | ||
discussed in class. It is not necessarily the best solution to the problem. | ||
In other words, I generally only use things we have covered up to this point | ||
in the class (with some exceptions which I will usually note). | ||
Python for Network Engineers | ||
https://pynet.twb-tech.com | ||
Learning Python | ||
Create a script that can login to a network device (using either telnet or SSH) | ||
and retrieve 'show version' from the device. | ||
Process the 'show version' output and store the below attributes in a | ||
NetworkDevice object: | ||
NetworkObject | ||
hostname | ||
ip | ||
username | ||
password | ||
device_type # router, switch, firewall, etc. | ||
vendor | ||
model | ||
os_version | ||
uptime # seconds | ||
serial_number | ||
This object should be stored to a file using pickle. | ||
Here is the output of running essentially this code against a test device | ||
(password stripped): | ||
$ python main_program.py | ||
Using SSH: | ||
hostname: twb-sf-881 | ||
ip: 10.220.88.1 | ||
username: pynet | ||
password: * | ||
device_type: router | ||
vendor: Cisco | ||
model: 881 | ||
os_version: 15.0(1)M4 | ||
uptime: 8978280 | ||
serial_number: FTX1512038X | ||
Using telnet: | ||
hostname: twb-sf-881 | ||
ip: 10.220.88.1 | ||
username: pynet | ||
password: * | ||
device_type: router | ||
vendor: Cisco | ||
model: 881 | ||
os_version: 15.0(1)M4 | ||
uptime: 8978280 | ||
serial_number: FTX1512038X | ||
Reading objects from pickle files: | ||
hostname: twb-sf-881 | ||
ip: 10.220.88.1 | ||
username: pynet | ||
password: * | ||
device_type: router | ||
vendor: Cisco | ||
model: 881 | ||
os_version: 15.0(1)M4 | ||
uptime: 8978280 | ||
serial_number: FTX1512038X | ||
hostname: twb-sf-881 | ||
ip: 10.220.88.1 | ||
username: pynet | ||
password: * | ||
device_type: router | ||
vendor: Cisco | ||
model: 881 | ||
os_version: 15.0(1)M4 | ||
uptime: 8978280 | ||
serial_number: FTX1512038X | ||
''' | ||
|
||
|
||
import time | ||
import pickle | ||
|
||
import ssh_connection as ssh | ||
import telnet_connection as telnet | ||
from show_version_parser import process_show_version | ||
|
||
|
||
class NetworkDevice(object): | ||
def __init__(self, ip, username, password): | ||
self.ip = ip | ||
self.username = username | ||
self.password = password | ||
|
||
|
||
def ssh_main(): | ||
''' | ||
Process show version using SSH | ||
''' | ||
|
||
ip = '10.220.88.1' | ||
username = 'pynet' | ||
password = '*' | ||
|
||
test_device = NetworkDevice(ip, username, password) | ||
|
||
(remote_conn_pre, remote_conn, output) = ssh.establish_connection(ip, username, password) | ||
output = ssh.disable_paging(remote_conn) | ||
|
||
remote_conn.send("\n") | ||
remote_conn.send("show version\n") | ||
|
||
# Read the output from the 'show version' command | ||
test_device.show_version = ssh.read_ssh_data(remote_conn) | ||
|
||
remote_conn_pre.close() | ||
process_show_version(test_device) | ||
|
||
# Print to stdout for verification | ||
net_device_verification(test_device) | ||
|
||
# Write object to a file | ||
with open('ssh_file.pkl', 'wb') as f: | ||
pickle.dump(test_device, f) | ||
|
||
|
||
def telnet_main(): | ||
''' | ||
Process show version using telnet | ||
''' | ||
|
||
ip = '10.220.88.1' | ||
username = 'pynet' | ||
password = '*' | ||
|
||
test_device2 = NetworkDevice(ip, username, password) | ||
|
||
remote_conn = telnet.establish_connection(ip, username, password) | ||
|
||
telnet.disable_paging(remote_conn) | ||
|
||
remote_conn.write("\n") | ||
remote_conn.write("show version\n") | ||
|
||
time.sleep(1) | ||
test_device2.show_version = remote_conn.read_very_eager() | ||
|
||
remote_conn.close() | ||
process_show_version(test_device2) | ||
|
||
# Print to stdout for verification | ||
net_device_verification(test_device2) | ||
|
||
# Write object to a file | ||
with open('telnet_file.pkl', 'wb') as f: | ||
pickle.dump(test_device2, f) | ||
|
||
|
||
def net_device_verification(net_device): | ||
''' | ||
Prints out a set of attributes for a NetworkDevice object | ||
''' | ||
|
||
print_attr = [ | ||
'hostname', | ||
'ip', | ||
'username', | ||
'password', | ||
'device_type', | ||
'vendor', | ||
'model', | ||
'os_version', | ||
'uptime', | ||
'serial_number', | ||
] | ||
|
||
# Uses getattr to get the right attribute | ||
for field in print_attr: | ||
val = getattr(net_device, field) | ||
print "%15s: %-40s" % (field, val) | ||
|
||
|
||
if __name__ == "__main__": | ||
|
||
print "Using SSH:" | ||
ssh_main() | ||
|
||
print "Using telnet:" | ||
telnet_main() | ||
|
||
print "\n" | ||
print "Reading objects from pickle files:" | ||
my_files = ['ssh_file.pkl', 'telnet_file.pkl'] | ||
for a_file in my_files: | ||
with open(a_file, 'rb') as f: | ||
netdev_obj = pickle.load(f) | ||
net_device_verification(netdev_obj) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import re | ||
from uptime import Uptime | ||
|
||
def process_show_version(net_device): | ||
''' | ||
Process the show_version output for net_device | ||
Assign the following attributes to the net_device object | ||
hostname | ||
device_type # router, switch, firewall, etc. | ||
vendor | ||
model | ||
os_version | ||
uptime # seconds | ||
serial_number | ||
''' | ||
|
||
show_ver = net_device.show_version | ||
|
||
# Process show_version output | ||
net_device.vendor, net_device.model = obtain_vendor_model(show_ver) | ||
net_device.os_version = obtain_os_version(show_ver) | ||
net_device.uptime = obtain_uptime(show_ver) | ||
net_device.hostname = obtain_hostname(show_ver) | ||
net_device.serial_number = obtain_serial_number(show_ver) | ||
net_device.device_type = obtain_device_type(net_device.model) | ||
|
||
|
||
def obtain_vendor_model(show_ver): | ||
|
||
# '(.+?) ' means any sequence of one or more characters followed by space (shortest match) | ||
match = re.search(r"Cisco (.+?) .+bytes of memory", show_ver) | ||
if match: | ||
return ("Cisco", match.group(1)) | ||
else: | ||
return None | ||
|
||
def obtain_os_version(show_ver): | ||
|
||
# (.+?), means any sequence of one or more characters followed by comma (shortest match) | ||
match = re.search(r"Cisco IOS Software.*Version (.+?),", show_ver) | ||
if match: | ||
return match.group(1) | ||
else: | ||
return None | ||
|
||
def obtain_uptime(show_ver): | ||
|
||
match = re.search(r".* uptime is .*", show_ver) | ||
|
||
if match: | ||
uptime_str = match.group().strip() | ||
uptime_obj = Uptime(uptime_str) | ||
return uptime_obj.uptime_seconds() | ||
else: | ||
return None | ||
|
||
def obtain_hostname(show_ver): | ||
''' | ||
Example string from Cisco IOS: | ||
twb-sf-881 uptime is 14 weeks, 4 days, 22 hours, 59 minutes | ||
return the hostname, else None | ||
''' | ||
|
||
match = re.search(r"(.+) uptime is .+", show_ver) | ||
if match: | ||
return match.group(1) | ||
else: | ||
return None | ||
|
||
def obtain_serial_number(show_ver): | ||
''' | ||
Example string from Cisco IOS: | ||
Processor board ID FTX1000008X | ||
return the serial_number, else None | ||
''' | ||
|
||
match = re.search(r"Processor board ID (.+)", show_ver) | ||
if match: | ||
return match.group(1).strip() | ||
else: | ||
return None | ||
|
||
def obtain_device_type(model): | ||
''' | ||
Determine the device_type based on the model | ||
''' | ||
|
||
if '881' in model: | ||
return 'router' | ||
else: | ||
return None | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import paramiko | ||
import time | ||
|
||
def disable_paging(remote_conn, command="terminal length 0\n", delay=1): | ||
|
||
remote_conn.send("\n") | ||
remote_conn.send(command) | ||
|
||
# Wait for the command to complete | ||
time.sleep(delay) | ||
|
||
output = remote_conn.recv(65535) | ||
|
||
return output | ||
|
||
|
||
def establish_connection(ip, username='', password=''): | ||
''' | ||
Use Paramiko to establish an SSH channel to the device | ||
Must return both return_conn_pre and return_conn so that the SSH | ||
connection is not garbage collected | ||
''' | ||
|
||
remote_conn_pre = paramiko.SSHClient() | ||
remote_conn_pre.set_missing_host_key_policy( | ||
paramiko.AutoAddPolicy()) | ||
|
||
remote_conn_pre.connect(ip, username=username, password=password) | ||
|
||
remote_conn = remote_conn_pre.invoke_shell() | ||
|
||
# Clear banner and prompt | ||
output = remote_conn.recv(65535) | ||
|
||
return (remote_conn_pre, remote_conn, output) | ||
|
||
|
||
def read_ssh_data(remote_conn, delay=1): | ||
''' | ||
Read the data from the ssh channel | ||
Uses a delay based mechansim | ||
''' | ||
|
||
# Wait for the command to complete | ||
time.sleep(delay) | ||
return remote_conn.recv(65535) | ||
|
||
|
||
if __name__ == "__main__": | ||
|
||
ip = '10.220.88.1' | ||
username = 'pynet' | ||
password = '*' | ||
|
||
(remote_conn_pre, remote_conn, output) = establish_connection(ip, username, password) | ||
output = disable_paging(remote_conn) | ||
|
||
remote_conn.send("\n") | ||
remote_conn.send("show version\n") | ||
|
||
output = read_ssh_data(remote_conn) | ||
print output | ||
|
||
remote_conn_pre.close() |
Oops, something went wrong.