#!/usr/bin/python3
# -*- coding: utf-8 -*-
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoAuthenticationException, NetMikoTimeoutException
import threading
import time
import datetime
import queue
def conn_info(ip):
dev = {
'device_type': 'huawei',
'host': ip,
'username':'用戶名',
'password': '密碼',
}
return dev
def conn_dev(dev_ip, ser_token):
sys_name = 's5720li-v200r019c10spc500.cc'
patch_name = 's5720li-v200r019sph009.pat'
oldsys_name = 's5720li-v200r011c10spc600.cc'
try:
dev_conn = ConnectHandler(**conn_info(dev_ip))
print("[%s] Connected." % dev_ip)
output = dev_conn.send_command('display startup') #查看啓動配置明細
sys_set, patch_set, oldsys_set = False, False, False
if sys_name in output:
sys_set = True
if patch_name in output:
patch_set = True
if oldsys_name in output:
oldsys_set = True
reboot = False
if not (sys_set and patch_set): #配置明細缺少指定的system或patch
#檢查指定的system或者patch的文件是否存在,如不存在則通過ftp server download
output = dev_conn.send_command('dir')
sys_got, patch_got = False, False
if sys_name in output:
sys_got = True
if patch_name in output:
patch_got = True
if sys_got and patch_got: #已有system或patch文件,直接設置下次啓用
#設定下次啓動運行指定的system和patch
dev_conn.send_command_timing('startup system ' + sys_name)
dev_conn.send_command_timing('startup patch ' + patch_name)
reboot = True #打開需要重啓的信號
else: #缺少system或patch文件,ftp download后,再設置下次啓用
#通過死循環,遇到令牌用光的情況下,等待15秒后再試
while True:
if ser_token.empty():
print("[%s] Server busy. Try after 15s ..." % dev_ip)
time.sleep(15)
else:
ser_ip = ser_token.get()
dev_conn.send_command_timing('ftp %s' % ser_ip)
dev_conn.send_command_timing('user')
dev_conn.send_command_timing('password')
if 'ftp' in dev_conn.find_prompt():
if not patch_got:
print('[%s] Download patch from %s ......' % (dev_ip, ser_ip))
down_start = datetime.datetime.now()
dev_conn.send_command_timing('get ' + patch_name)
down_end = datetime.datetime.now()
print('[%s] Download patch done. seconds: %d s' % (dev_ip, (down_end - down_start).seconds))
if not sys_got:
print('[%s] Download system from %s ......' % (dev_ip, ser_ip))
down_start = datetime.datetime.now()
dev_conn.send_command_timing('get ' + sys_name, delay_factor=8)
down_end = datetime.datetime.now()
print('[%s] Download system done. seconds: %s s' % (dev_ip, (down_end - down_start).seconds))
if 'ftp' in dev_conn.find_prompt():
dev_conn.send_command_timing('q')
dev_conn.send_command_timing('startup system ' + sys_name)
dev_conn.send_command_timing('startup patch ' + patch_name)
reboot = True
ser_token.put(ser_ip) #download完将令牌交还
break #download完成,跳出死循环
else: #配置明細包含指定的system或patch
#假如配置中有舊的system,表明需要從重新啓動
if oldsys_set:
reboot = True
else:
print('[%s] System firmware and patch match!' % dev_ip)
#檢測重啓信號,如是則重新啓動
if reboot:
dev_conn.send_command_timing('reboot')
dev_conn.send_command_timing('y')
print('[%s] Rebooting ...' % dev_ip)
dev_conn.disconnect()
except NetMikoAuthenticationException:
print("[%s] Error! Please check username or password ..." % dev_ip)
except NetMikoTimeoutException:
print("[%s] Error! Connect time out ..." % dev_ip)
if __name__ == "__main__":
devs_ip = ['192.168.2.124', '192.168.2.125', '192.168.2.126', '192.168.2.127', '192.168.2.128', '192.168.2.129', '192.168.2.130', '192.168.2.131']
sers_ip = ['192.168.2.73', '192.168.2.74',]
sers_maxclient = 5 #服務器只允許同時5個連接
#服務器下載令牌,客戶端取得令牌后才進行download
q_token = queue.Queue()
for sc in sers_ip * sers_maxclient:
q_token.put(sc)
ts = [] #用於阻塞主綫程
for ip in devs_ip:
t = threading.Thread(target=conn_dev, args=(ip, q_token))
t.start()
ts.append(t)
for t in ts:
t.join()