您的位置:首页 > 编程语言 > Python开发

人生苦短,我用Python(三)—通过Python实现网络设备指定指标的收集与指标的图形化展示

2018-10-14 16:14 471 查看

写在前面:

博主自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的使用说明,见如下链接:

https://pynet.twb-tech.com/blog/automation/netmiko.html

值得一说的是Netmiko模块是由 Kirk Byers开发,CCIE编号6243,膜拜大神!

本文中的代码,以运行在EVE-NG模拟器中的思科设备,作为目标网络设备,测试代码的运行情况。

下面看具体代码:

[code]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命令,查看。

要断开连接,则执行如下代码:

[code]net_connect.disconnect()

至此,我们可以实现控制端与网络设备的连接与断开。

如何实现网络设备指定指标的提取与收集

在实现了与网络设备的连接后,要实现指定指标的提取和收集,我们首先要在网络设备执行相关指标的查看命令,然后再将关心的指标的数值提取出来。

仍然是通过netmiko模块,输入想要在网络设备上执行的相关命令。

以查看接口各项指标为例,思科设备命令为:

show interfaces Eth0/0

在python中,利用netmiko模块实现代码如下:

[code]cmd = 'show interfaces Eth0/0' 
print('正在执行' + cmd)
output = net_connect.send_command(cmd)

如果是针对,同一个接口的各项指标,以一定的时间间隔,反复查询,可以利用time模块,进行时间的间隔,结合for语句,循环执行。

如果是针对,不同接口的各项指标进行对比的需求,同样是利用for语句,进行循环执行,实现代码如下:

[code]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)

通过运行上面的代码,我们会得到一个设备的接口列表

[code]interfaceList=['接口名称', 'eth0/0', 'eth0/1', 'eth0/2', 'eth0/3']

这样,每一次的output结果,是每一次执行查看指定接口命令的完整的输出,其输出结果如下:

[code]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这个具体的数值,都提取出来,实现代码如下:

[code]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分钟出向流量的指标

通过运行上面的代码,我们可以得到如下几个列表:

[code]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中,可以通过如下代码实现:

[code]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模块了,该模块的使用也非常简单,直接看代码:

[code]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实现一些网络设备相关的自动化功能的时候,常常在通过代码实现的过程中,不断有新的想法冒出来,想到除了一开始的目标以外,我们还能实现哪些功能,这一次的图像绘制,就是在实现了指标的收集后,想到的可以增加的功能,并且很快就得以实现,同时进一步扩展了自己的知识领域。并且在代码实现的过程中,注意到代码的通用性,避免需要反复的适配和调整,同时方便以后的调用。

每次完成一个功能的开发,对开发的过程进行回溯,都感觉功能的实现似乎并不难,无非是难者不会与会者不难的区别,进行整理,也不过了了几页。然而在开发过程中碰到的困难、增长的知识、积累的经验等等,却不是这了了几页就可以讲清楚的。我们经常听到一些说法,代码不过是实现某个思路的一种手段,代码只是一种工具等等。这些话固然没有错,但是代码给与我们的,除了实现我们最终想要达到的目标以外,还有很多值得我们去进一步的思考和总结。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: