1. 程式人生 > >人生苦短,我用Python(三)—通過Python實現網路裝置指定指標的收集與指標的圖形化展示

人生苦短,我用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實現一些網路裝置相關的自動化功能的時候,常常在通過程式碼實現的過程中,不斷有新的想法冒出來,想到除了一開始的目標以外,我們還能實現哪些功能,這一次的影象繪製,就是在實現了指標的收集後,想到的可以增加的功能,並且很快就得以實現,同時進一步擴充套件了自己的知識領域。並且在程式碼實現的過程中,注意到程式碼的通用性,避免需要反覆的適配和調整,同時方便以後的呼叫。

每次完成一個功能的開發,對開發的過程進行回溯,都感覺功能的實現似乎並不難,無非是難者不會與會者不難的區別,進行整理,也不過了了幾頁。然而在開發過程中碰到的困難、增長的知識、積累的經驗等等,卻不是這了了幾頁就可以講清楚的。我們經常聽到一些說法,程式碼不過是實現某個思路的一種手段,程式碼只是一種工具等等。這些話固然沒有錯,但是程式碼給與我們的,除了實現我們最終想要達到的目標以外,還有很多值得我們去進一步的思考和總結。