Skip to content

Commit

Permalink
Class10 exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
ktbyers committed Jun 12, 2014
1 parent 4d86f46 commit 2fa4163
Show file tree
Hide file tree
Showing 5 changed files with 514 additions and 0 deletions.
211 changes: 211 additions & 0 deletions learnpy_ecourse/class10/main_program.py
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)

print

if __name__ == "__main__":

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

97 changes: 97 additions & 0 deletions learnpy_ecourse/class10/show_version_parser.py
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

67 changes: 67 additions & 0 deletions learnpy_ecourse/class10/ssh_connection.py
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()
Loading

0 comments on commit 2fa4163

Please sign in to comment.