人生苦短,我用Python(三)—通過Python實現網路裝置指定指標的收集與指標的圖形化展示
寫在前面:
博主自2018年8月底開始,堅持每週更新一篇技術類部落格,含本篇文章在內,目前已經更新了八篇文章。除十一假期外,堅持每週更新。希望自己能堅持下去。
目前已經開啟了三個系列的文章,分別是:
- 《人生苦短,我用Python》——已釋出三篇文章
- 《那些你應該知道的知識》——已釋出四篇文章
- 《割接的那些事》——已釋出一篇文章
希望能通過這種方式,記錄自己的成長,將實戰過程中碰到的零碎的知識進行整理,同時也希望能對每一位讀者提供幫助。
通過本文你將瞭解到,通過python
- 如何連線到網路裝置
- 如何實現網路裝置指定指標的提取與收集,本文將以收集頻寬相關指標作為示例
- 如何進行簡單的圖形繪製
如何連線到網路裝置
首先,我們如果想利用python實現網路裝置的巡檢,甚至自動配置等功能,我們首先要能夠與網路裝置相連線。
目前,要實現控制端與目標端網路裝置連線有兩種方式:
1、通過傳統的telnet或SSH,與網路裝置連線,然後執行命令,獲取相應輸出結果,達到自動巡檢的目的。
2、通過網路裝置本身開放的api,實現自動化的相關功能。
推薦各類網路裝置在支援開放api的情況下,使用第二種方式與網路裝置相連。由網路裝置廠商官方開放的API介面的穩定性要遠遠強於通過telnet或SSH,連線到網路裝置上執行相關命令的這種方式。
然而,直到今天,大量的現網執行的裝置中是沒有開放的API介面的,即使是一些近些年新推出的產品支援了開放API介面,其開放的功能是否齊全和完善,也有待進一步的確認。
所以,這導致了,若想要針對現網裝置中大量的傳統網路裝置,實現自動化的相關功能,採用telnet或SSH與網路裝置進行連線,然後輸入相關命令,獲取相應結果的方式,是目前比較現實的選擇。
後續博主也會針對一些開放API介面的裝置,例如F5、防火牆、Cisco NX-OS裝置等,作進一步的網路自動化相關的研究和嘗試。
本文,所描述的與網路裝置連線的方式,為控制端與網路裝置通過SSH或Telnet連線。要實現這兩種連線方式,分別需要用到兩個第三方模組
Netmiko—實現與網路裝置的SSH連線
Telnetlib—實現與網路裝置的telnet連線
這兩個模組,可以說是博主目前實現網路裝置各項自動化功能最重要的兩個模組。
其中,telnetlib可以說支援所有可以通過telnet連線的所有型別的裝置、不只是網路裝置,這個模組需要你根據不同的裝置型別,確定其回顯值,從而輸入下一步命令。
博主主要用這個模組,實現與部分國產廠商的網路裝置的連線,如銳捷、邁普等。
而使用Netmiko模組,該模組目前已經與很多一線網路裝置廠商做過適配,使用者可以直接使用該模組登入網路裝置,無需進行額外的適配。可惜的是很多國產廠商並不在其已經完整測試過的列表中。
Netmiko支援的裝置情況如下:
目前博主已經嘗試過通過該模組與思科裝置、華為裝置進行連線。HP Comware7也在其列表中,可見H3C裝置應該同樣支援。能夠支援Cisco、華為、H3C這三個品牌,相信應付網路工程師大部分的工作場景應該足夠了
與思科裝置連線很正常,可以正常使用,而·與華為裝置進行連線時,在需要敲super進入裝置特權模式的裝置中,碰到了一些問題,目前還沒有解決。在登入華為裝置的使用者許可權足夠,不需要輸入super命令的情況下,可使用netmiko模組進行相關自動化功能的嘗試。
關於Netmiko的使用說明,見如下連結:
值得一說的是Netmiko模組是由 Kirk Byers開發,CCIE編號6243,膜拜大神!
本文中的程式碼,以執行在EVE-NG模擬器中的思科裝置,作為目標網路裝置,測試程式碼的執行情況。
下面看具體程式碼:
deviceName = 'R1'
host = '192.168.126.101'
print(host)
deviceType = 'cisco_ios'
username = 'admin'
password = '12345678'
device = {'device_type': deviceType,
'ip': host,
'username': username,
'password': password}
net_connect = ConnectHandler(**device)
sshConfirm = net_connect.find_prompt()
print('已成功登入 ' + sshConfirm)
通過執行以上程式,可登入到網路裝置中。
在網路裝置中,可以通過show users命令,檢視。
要斷開連線,則執行如下程式碼:
net_connect.disconnect()
至此,我們可以實現控制端與網路裝置的連線與斷開。
如何實現網路裝置指定指標的提取與收集
在實現了與網路裝置的連線後,要實現指定指標的提取和收集,我們首先要在網路裝置執行相關指標的檢視命令,然後再將關心的指標的數值提取出來。
仍然是通過netmiko模組,輸入想要在網路裝置上執行的相關命令。
以檢視介面各項指標為例,思科裝置命令為:
show interfaces Eth0/0
在python中,利用netmiko模組實現程式碼如下:
cmd = 'show interfaces Eth0/0'
print('正在執行' + cmd)
output = net_connect.send_command(cmd)
如果是針對,同一個介面的各項指標,以一定的時間間隔,反覆查詢,可以利用time模組,進行時間的間隔,結合for語句,迴圈執行。
如果是針對,不同介面的各項指標進行對比的需求,同樣是利用for語句,進行迴圈執行,實現程式碼如下:
interfaceList=['介面名稱']
intNumber=3#介面總數
for i in range(0, intNumber+1):
ethName='eth0/%d'%i
interfaceList.append(ethName)
for i in range(1,len(interfaceList)):
cmd = 'show interfaces %s' %interfaceList[i]
print('正在執行' + cmd)
output = net_connect.send_command(cmd)
通過執行上面的程式碼,我們會得到一個裝置的介面列表
interfaceList=['介面名稱', 'eth0/0', 'eth0/1', 'eth0/2', 'eth0/3']
這樣,每一次的output結果,是每一次執行檢視指定介面命令的完整的輸出,其輸出結果如下:
R1#show interfaces Eth0/0
Ethernet0/0 is up, line protocol is up
Hardware is AmdP2, address is aabb.cc00.0100 (bia aabb.cc00.0100)
Internet address is 192.168.126.101/24
MTU 1500 bytes, BW 10000 Kbit/sec, DLY 1000 usec,
reliability 255/255, txload 1/255, rxload 1/255
Encapsulation ARPA, loopback not set
Keepalive set (10 sec)
ARP type: ARPA, ARP Timeout 04:00:00
Last input 00:00:00, output 00:00:00, output hang never
Last clearing of "show interface" counters never
Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
Queueing strategy: fifo
Output queue: 0/40 (size/max)
5 minute input rate 1000 bits/sec, 3 packets/sec
5 minute output rate 0 bits/sec, 0 packets/sec
88256 packets input, 9574723 bytes, 0 no buffer
Received 46121 broadcasts (0 IP multicasts)
0 runts, 7 giants, 0 throttles
6 input errors, 0 CRC, 0 frame, 0 overrun, 6 ignored
0 input packets with dribble condition detected
63970 packets output, 9145468 bytes, 0 underruns
0 output errors, 0 collisions, 1 interface resets
12927 unknown protocol drops
0 babbles, 0 late collision, 0 deferred
0 lost carrier, 0 no carrier
0 output buffer failures, 0 output buffers swapped out
在拿到了輸出結果的情況下,如何針對我們關心的指標進行提取呢?
這裡便需要用到正則表示式,博主的正則表示式水平一般,處於模仿階段,關於正則表示式的使用方法,就不在這裡展開了。
針對上面的output輸出結果,我們主要關心當前介面的頻寬,5分鐘入向速率,和5分鐘出向速率。
以介面頻寬為例,在output中,通過BW 10000 Kbit/sec,我們可以知道當前的介面頻寬為10000Kbit/sec,也就是10Mbps,我們希望能夠在output中將BW 10000 Kbit/sec這個完整的指標項和10000這個具體的數值,都提取出來,實現程式碼如下:
def deviceIndexCollect(cmd,indexName,startString,endString,dstIndexList,dstValueList):
index = re.search("(%s*)(\s)([0-9]*)(\s)(%s*)" % (startString,endString), output, re.S).group() #提取以'指定開頭'‘空格’‘數字’‘空格’‘指定結尾’為格式的字串
print('指標'+indexName+'->' + ' ' + index)
dstIndexList.append(index)#將提取出來的字串新增到指標的列表中
a = re.findall(r"\d+\.?\d*", index)#在提取出來的字串中,將數字提取出來
index_value=a[len(a)-1]#進一步提取數字列表中,最後一個數值
print('指標' + indexName + '數值'+'='+index_value)
dstValueList.append(index_value)#將具體指標值新增到數值列表中
deviceIndexCollect(cmd, '頻寬', 'BW', 'Kbit/sec', index_BWList, index_BW_valueList) #提取頻寬的指標
deviceIndexCollect(cmd, '5分鐘入向流量', '5 minute input rate', 'bits/sec', index_5minInputList,index_5minInput_valueList)#提取5分鐘入向流量的指標
deviceIndexCollect(cmd, '5分鐘出向流量', '5 minute output rate', 'bits/sec', index_5minOutputList,index_5minOutput_valueList)#提取5分鐘出向流量的指標
通過執行上面的程式碼,我們可以得到如下幾個列表:
index_BWList=['頻寬', 'BW 10000 Kbit/sec', 'BW 10000 Kbit/sec', 'BW 10000 Kbit/sec', 'BW 10000 Kbit/sec']
index_BW_valueList=['數值', '10000', '10000', '10000', '10000']
index_5minInputList=['5分鐘入向流量', '5 minute input rate 9000 bits/sec', '5 minute input rate 0 bits/sec', '5 minute input rate 0 bits/sec', '5 minute input rate 0 bits/sec']
index_5minInput_valueList=['數值', '9000', '0', '0', '0']
index_5minOutputList=['5分鐘出向流量', '5 minute output rate 0 bits/sec', '5 minute output rate 0 bits/sec', '5 minute output rate 0 bits/sec', '5 minute output rate 0 bits/sec']
index_5minOutput_valueList=['數值', '0', '0', '0', '0']
至此,我們已經將我們關心的指標,和指標對應的數值提取了出來。
下面,將這些值收集在一起,我選擇的是,將這些值填寫到excel中,可以通過如下程式碼實現:
def fillInExcel(index,srcList,valueList1,valueList2,valueList3,valueList4,valueList5,valueList6):
sheetA = wb[index]
for i in range(len(srcList)):
sheetA['A%d' % (i + 1)] = srcList[i]
for i in range(len(valueList1)):
sheetA['B%d'%(i+1)]=valueList1[i]
for i in range(len(valueList2)):
sheetA['C%d'%(i+1)]=valueList2[i]
for i in range(len(valueList3)):
sheetA['D%d'%(i+1)]=valueList3[i]
for i in range(len(valueList4)):
sheetA['E%d'%(i+1)]=valueList4[i]
for i in range(len(valueList5)):
sheetA['F%d'%(i+1)]=valueList5[i]
for i in range(len(valueList6)):
sheetA['G%d'%(i+1)]=valueList6[i]
wb=Workbook()
wb.create_sheet("介面流量指標",0)
fillInExcel('介面流量指標', interfaceList,index_BWList, index_BW_valueList, index_5minInputList, index_5minInput_valueList, index_5minOutputList, index_5minOutput_valueList)
file = 'NetInerfacesBWSeq.xlsx'
wb.save(file)
print(file + '表格填寫完成')
至此,我們可以得到下面的表格:
於是,通過以上程式碼,我們可以實現指定指標的提取,和收集。
除了文中提到的頻寬指標外,採用類似的方法,我們可以提取網路裝置上任何可以通過命令方方式檢視的指標,只需要修改正則表示式引數,以及要填寫的excel的內容即可。
例如,我們可以每隔一段時間,檢視裝置的cpu和記憶體使用情況,得到如下表格:
我們也可以利用excel中,我們熟悉的各項功能,對資料作進一步的處理,例如資料的加減乘除、資料的排序等等。我們同樣可以通過excel繪製相關的圖示。
然而,我們如何通過python實現簡單的圖形繪製呢?
如何進行簡單的圖形繪製
要實現圖形的繪製,不得不提大名鼎鼎的matplotlib模組了,該模組的使用也非常簡單,直接看程式碼:
import pylab as plt
x= interfaceList#將介面名稱作為X軸的值
y = list(map(int, index_5minInput_valueList))#將5分鐘入向流量作為Y軸的值
y1= list(map(int, index_5minOutput_valueList))#將5分鐘出向流量作為Y軸的值
plt.figure()
plt.plot(x, y, 'ob-')#繪製5分鐘入向流量的折線圖,繪製為藍色的線
plt.plot(x, y1, 'or-')#繪製5分鐘出向流量的折線圖,繪製為紅色的線
plt.show()#顯示影象
其中,需要注意的是,要使用pylab繪製數字相關影象,要繪製出來的影象有數字的相關意義,x軸或y軸的值,一定要是int格式的。
下面我們在模擬環境中,進行一些ping操作,模擬流量情況,得到的影象如下:
我通過以上程式碼,連線公司的一臺華為接入交換機,分別得到的介面頻寬影象和CPU記憶體使用情況的影象,如下:
關於matplotlib更多的使用方法,博主將在之後的學習中不斷嘗試。
總結
現在,我們可以通過telnet或ssh的方式,登入到網路裝置上,執行相關命令,獲取執行的結果。
利用正則表示式,對獲取的結果進行提取,同時可以將提取到的值填寫到excel中。
最後,我們可以通過matplotlib繪製簡單的影象,我們可以通過影象,觀察裝置某一項指標的排序,或者一些指標的趨勢圖。
尾巴
在每一次,想要通過python實現一些網路裝置相關的自動化功能的時候,常常在通過程式碼實現的過程中,不斷有新的想法冒出來,想到除了一開始的目標以外,我們還能實現哪些功能,這一次的影象繪製,就是在實現了指標的收集後,想到的可以增加的功能,並且很快就得以實現,同時進一步擴充套件了自己的知識領域。並且在程式碼實現的過程中,注意到程式碼的通用性,避免需要反覆的適配和調整,同時方便以後的呼叫。
每次完成一個功能的開發,對開發的過程進行回溯,都感覺功能的實現似乎並不難,無非是難者不會與會者不難的區別,進行整理,也不過了了幾頁。然而在開發過程中碰到的困難、增長的知識、積累的經驗等等,卻不是這了了幾頁就可以講清楚的。我們經常聽到一些說法,程式碼不過是實現某個思路的一種手段,程式碼只是一種工具等等。這些話固然沒有錯,但是程式碼給與我們的,除了實現我們最終想要達到的目標以外,還有很多值得我們去進一步的思考和總結。