Skip to content

Commit 116faae

Browse files
authored
Create IOS_update_threating_w_stack.py
1 parent f899215 commit 116faae

File tree

1 file changed

+326
-0
lines changed

1 file changed

+326
-0
lines changed

IOS_update_threating_w_stack.py

Lines changed: 326 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,326 @@
1+
"""
2+
Category: Netmiko Config Script
3+
Author: nouse4it <github@schlueter-online.net>
4+
5+
IOS_update_threating_w_stack.py
6+
Illustrate the following conecepts:
7+
- Update IOS of given IOS-based Switch; Test with 2960x
8+
-- Including 2960x-Stacks
9+
- Process handling happend parallel by threating
10+
- Including MD5-Check after copy of Software to Switch to ensure integrity
11+
"""
12+
13+
__author__ = "nouse4it"
14+
__author_email__ = "github@schlueter-online.net"
15+
__copyright__ = "Copyright (c) 2020 nouse4it "
16+
17+
# Importing all needed Modules
18+
import netmiko
19+
from netmiko import SCPConn,ConnectHandler
20+
import os,sys,subprocess,re
21+
from pprint import pprint
22+
import json
23+
import threading
24+
import time
25+
26+
#------------------------------------------------------------------------------
27+
def check_md5(filename):
28+
command = 'md5sum '+filename
29+
o = subprocess.getoutput(command)
30+
output = o.split(' ')
31+
return output[0]
32+
#------------------------------------------------------------------------------
33+
def set_boot(net_connect,file):
34+
get_old_vers = net_connect.send_command('sh version | i System image file is')
35+
old_vers = get_old_vers.split('"')[1]
36+
net_connect.config_mode()
37+
net_connect.send_command('boot system switch all flash:{},{} '.format(file,old_vers))
38+
net_connect.exit_config_mode()
39+
output = net_connect.send_command('sh boot | i BOOT')
40+
print('Following Boot String was set: {}', format(output))
41+
net_connect.send_command('wr')
42+
#------------------------------------------------------------------------------
43+
def reload(net_connect):
44+
net_connect.send_command('reload',expect_string='')
45+
net_connect.send_command('\n')
46+
#------------------------------------------------------------------------------
47+
def archive_run(net_connect,filename):
48+
result = net_connect.send_command("show run")
49+
# close SSH connection
50+
# net_connect.disconnect()
51+
file = open(filename,"w")
52+
file.write(result)
53+
file.close()
54+
#------------------------------------------------------------------------------
55+
def verify_md5(net_connect,file,md5):
56+
result = net_connect.send_command("verify /md5 flash:{} {}".format(file,md5))
57+
# close SSH connection
58+
# net_connect.disconnect()
59+
reg = re.compile(r'Verified')
60+
verify = reg.findall(result)
61+
if verify:
62+
result = True
63+
else:
64+
result = False
65+
return result
66+
#------------------------------------------------------------------------------
67+
def verify_space(net_connect,file):
68+
result = net_connect.send_command("show flash:")
69+
# close SSH connection
70+
# net_connect.disconnect()
71+
reg = re.compile(r'(\d+)\sbytes\sfree')
72+
space = int(reg.findall(result)[0])
73+
reg = re.compile(r'.*-rwx.*({})'.format(file))
74+
exist = reg.findall(result)
75+
f_size = os.path.getsize(file)
76+
if space >= f_size:
77+
result = 'True'
78+
if space < f_size:
79+
result = 'False'
80+
if exist:
81+
exist = 'True'
82+
else:
83+
exist = 'False'
84+
return result,exist
85+
#------------------------------------------------------------------------------
86+
def transfer_file(net_connect,file):
87+
net_connect.config_mode()
88+
net_connect.send_command('ip scp server enable')
89+
scp_conn = SCPConn(net_connect)
90+
s_file = file
91+
d_file = file
92+
scp_conn.scp_transfer_file(s_file, d_file)
93+
#------------------------------------------------------------------------------
94+
def stack_check(net_connect,file):
95+
output = net_connect.send_command("sh run | i GigabitEthernet")
96+
intf = output.splitlines()
97+
if 'interface GigabitEthernet4/0/1' in intf:
98+
print('It´s a 4-Switch Stack')
99+
print('Copying Image to flash4:')
100+
net_connect.send_command('copy flash:%s flash4:' %(file), expect_string='Destination filename')
101+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
102+
103+
print('Copying Image to flash3:')
104+
net_connect.send_command('copy flash:%s flash3:' %(file), expect_string='Destination filename')
105+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
106+
107+
print('Copying Image to flash2:')
108+
net_connect.send_command('copy flash:%s flash2:' %(file), expect_string='Destination filename')
109+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
110+
111+
elif 'interface GigabitEthernet3/0/1' in intf:
112+
print('It´s a 3-Switch Stack')
113+
print('Copying Image to flash3:')
114+
net_connect.send_command('copy flash:%s flash3:' %(file), expect_string='Destination filename')
115+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
116+
117+
print('Copying Image to flash2:')
118+
net_connect.send_command('copy flash:%s flash2:' %(file), expect_string='Destination filename')
119+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
120+
121+
elif 'interface GigabitEthernet2/0/1' in intf:
122+
print('It´s a 2-Switch Stack')
123+
print('Copying Image to flash2:')
124+
net_connect.send_command('copy flash:%s flash2:' %(file), expect_string='Destination filename')
125+
net_connect.send_command('\n', expect_string=r'#', delay_factor=5)
126+
127+
elif 'interface GigabitEthernet1/0/1' in intf:
128+
print('It´s not a Stack besides quoted! No additional copy needed')
129+
130+
return
131+
#------------------------------------------------------------------------------
132+
def read_devices( devices_filename ):
133+
134+
devices = {} # create our dictionary for storing devices and their info
135+
136+
with open( devices_filename ) as devices_file:
137+
138+
for device_line in devices_file:
139+
140+
device_info = device_line.strip().split(',') #extract device info from line
141+
142+
device = {'ipaddr': device_info[0],
143+
'type': device_info[1],
144+
'name': device_info[2],
145+
'stack': device_info[3]} # create dictionary of device objects ...
146+
147+
devices[device['ipaddr']] = device # store our device in the devices dictionary
148+
# note the key for devices dictionary entries is ipaddr
149+
150+
print ('\n----- devices --------------------------')
151+
pprint( devices )
152+
153+
return devices
154+
155+
#------------------------------------------------------------------------------
156+
def command_worker( device, creds ):
157+
158+
#---- Connect to the device ----
159+
if device['type'] == 'cisco-nxos': device_type = 'cisco_nxos'
160+
elif device['type'] == 'cisco-ios': device_type = 'cisco_ios'
161+
else: device_type = 'cisco_ios' # attempt Cisco IOS as default
162+
163+
print ('---- Connecting to device {0}, username={1}, password={2}'.format( device['ipaddr'],
164+
creds[0], creds[1] ))
165+
# ---- Connect to the device
166+
session = ConnectHandler(device_type=device_type, ip=device['ipaddr'],
167+
username=creds[0], password=creds[1])
168+
169+
if device_type == 'cisco_nxos':
170+
#verify if there is enough free space on device to upload ios file
171+
net_connect = session
172+
ver = verify_space(net_connect,file_s)
173+
print("\n\n Verifying sufficient space available on the file system ... %s\n\n" %(device['ipaddr']))
174+
175+
if ver[0] == 'True' and ver[1] == 'False':
176+
print("\n\n Success! - proceed with image upload")
177+
print ("\n\nUploading file : %s ...\n\n" %(file_s))
178+
#transferring file to device
179+
net_connect = session
180+
transfer_file(net_connect,file_s)
181+
print ("\n\nSuccess! - upload file: %s to device: %s was successfull ... \n\n" % (file_s,device['ipaddr']))
182+
183+
#veryfing md5
184+
net_connect.exit_config_mode()
185+
md5 = check_md5(file_s)
186+
print ("\n\nVerifying md5 checksum on device ... %s\n\n" %(device['ipaddr']))
187+
net_connect = session
188+
v_md5 = verify_md5(net_connect, file_s,md5)
189+
if v_md5 == True:
190+
print("\n\n MD5 Check... Success! - Starting archive running config")
191+
filename = device['ipaddr']+"-running-config.txt"
192+
print ("\n\nSaving running config into file: %s \n\n" %(filename))
193+
archive_run(net_connect,filename)
194+
print("\n\n Archvie Config... Success! - proceed with inserting boot system command")
195+
set_boot(net_connect, file_s)
196+
print("\n\n Inserting Boot System Command... Success! - proceed with reload")
197+
try:
198+
reload(net_connect)
199+
except:
200+
print("Reloading ... ")
201+
else:
202+
print("\n\n Abort !!!\n\n")
203+
else:
204+
print("\n\n Error veryfiing md5 checksum on device, quitting !!!\n\n")
205+
206+
elif ver[0] == 'False' and ver[1] == 'False':
207+
print("\n\n Not enough free space on device ... %s \n\n" %(device['ipaddr']))
208+
209+
elif ver[1] == 'True':
210+
print ("\n\nFile already uploaded on device ... %s \n\n" %(device['ipaddr']))
211+
212+
if device_type == 'cisco_ios' and device['stack'] == 'yes':
213+
#verify if there is enough free space on device to upload ios file
214+
net_connect = session
215+
ver = verify_space(net_connect,file_s)
216+
print("\n\n Verifying sufficient space available on the file system ... %s\n\n" %(device['ipaddr']))
217+
218+
if ver[0] == 'True' and ver[1] == 'False':
219+
print("\n\n Success! - proceed with image upload")
220+
print ("\n\nUploading file : %s ...\n\n" %(file_s))
221+
#transferring file to device
222+
net_connect = session
223+
transfer_file(net_connect,file_s)
224+
print ("\n\nSuccess! - upload file: %s to device: %s was successfull ... \n\n" % (file_s,device['ipaddr']))
225+
226+
#veryfing md5
227+
net_connect.exit_config_mode()
228+
md5 = check_md5(file_s)
229+
print ("\n\nVerifying md5 checksum on device ... %s\n\n" %(device['ipaddr']))
230+
net_connect = session
231+
v_md5 = verify_md5(net_connect, file_s,md5)
232+
if v_md5 == True:
233+
print("\n\n MD5 Check... Success! - Starting check how many Switches in Stack")
234+
net_connect.exit_config_mode()
235+
stack_check(net_connect,file_s)
236+
filename = device['ipaddr']+"-running-config.txt"
237+
print ("\n\nSaving running config into file: %s \n\n" %(filename))
238+
archive_run(net_connect,filename)
239+
print("\n\n Archvie Config... Success! - proceed with inserting boot system command")
240+
set_boot(net_connect, file_s)
241+
print("\n\n Inserting Boot System Command... Success! - proceed with reload")
242+
try:
243+
reload(net_connect)
244+
except:
245+
print("Reloading ... ")
246+
else:
247+
print("\n\n Abort !!!\n\n")
248+
else:
249+
print("\n\n Error veryfiing md5 checksum on device, quitting !!!\n\n")
250+
251+
elif ver[0] == 'False' and ver[1] == 'False':
252+
print("\n\n Not enough free space on device ... %s \n\n" %(device['ipaddr']))
253+
254+
elif ver[1] == 'True':
255+
print ("\n\nFile already uploaded on device ... %s \n\n" %(device['ipaddr']))
256+
257+
if device_type == 'cisco_ios' and device['stack'] == 'no':
258+
#verify if there is enough free space on device to upload ios file
259+
net_connect = session
260+
ver = verify_space(net_connect,file_s)
261+
print("\n\n Verifying sufficient space available on the file system ... %s\n\n" %(device['ipaddr']))
262+
263+
if ver[0] == 'True' and ver[1] == 'False':
264+
print("\n\n Success! - proceed with image upload")
265+
print ("\n\nUploading file : %s ...\n\n" %(file_s))
266+
#transferring file to device
267+
net_connect = session
268+
transfer_file(net_connect,file_s)
269+
print ("\n\nSuccess! - upload file: %s to device: %s was successfull ... \n\n" % (file_s,device['ipaddr']))
270+
271+
#veryfing md5
272+
net_connect.exit_config_mode()
273+
md5 = check_md5(file_s)
274+
print ("\n\nVerifying md5 checksum on device ... %s\n\n" %(device['ipaddr']))
275+
net_connect = session
276+
v_md5 = verify_md5(net_connect, file_s,md5)
277+
if v_md5 == True:
278+
print("\n\n MD5 Check... Success! - Starting archive running config")
279+
filename = device['ipaddr']+"-running-config.txt"
280+
print ("\n\nSaving running config into file: %s \n\n" %(filename))
281+
archive_run(net_connect,filename)
282+
print("\n\n Archvie Config... Success! - proceed with inserting boot system command")
283+
set_boot(net_connect, file_s)
284+
print("\n\n Inserting Boot System Command... Success! - proceed with reload")
285+
try:
286+
reload(net_connect)
287+
except:
288+
print("Reloading ... ")
289+
else:
290+
print("\n\n Abort !!!\n\n")
291+
else:
292+
print("\n\n Error veryfiing md5 checksum on device, quitting !!!\n\n")
293+
294+
elif ver[0] == 'False' and ver[1] == 'False':
295+
print("\n\n Not enough free space on device ... %s \n\n" %(device['ipaddr']))
296+
297+
elif ver[1] == 'True':
298+
print ("\n\nFile already uploaded on device ... %s \n\n" %(device['ipaddr']))
299+
300+
session.disconnect()
301+
302+
return
303+
304+
#==============================================================================
305+
# ---- Main: Run Commands
306+
#==============================================================================
307+
308+
file_s = input("Enter Image Filename: ")
309+
username = input("Enter Username: ")
310+
password = input("Enter Password: ")
311+
312+
devices = read_devices('devices-file')
313+
creds = (username, password)
314+
315+
config_threads_list = []
316+
317+
for ipaddr,device in devices.items():
318+
print('Creating thread for: ', device)
319+
config_threads_list.append(threading.Thread(target=command_worker, args=(device, creds)))
320+
321+
print('\n---- Begin running command threading ----\n')
322+
for config_thread in config_threads_list:
323+
config_thread.start()
324+
325+
for config_thread in config_threads_list:
326+
config_thread.join()

0 commit comments

Comments
 (0)