python-交换机巡检自动化

​ 因为了解到python可以实现自动化的巡检功能,所以开始学习了《Python编程 从入门到实践》。通过一段时间的学习,将这本书的前11章看完,并开始搜索交换机巡检的相关模板,发现别人写的代码完全看不懂,很多模块,根本看不懂模块。经过一段时间的研究,要巡检,得学会以下几个模块:time、os、Netmiko、xlwt、re。
关于交换机的交互模块,有些大神用的是pexpect模块,使用 pexpect.spawn.sendline() 来发送交换机的命令和 pexpect.swapn.expect() 来验证输出是否符合要求。而我这次所使用的就是 Netmiko
我从开始学习到能ctrl+v出自己想要的脚本的过程如下:

《Python编程 从入门到实践》——百度大神的脚本——了解大神脚本中模块的功能——根据需求自己写脚本

接下来我们开始了解编写脚本,所需要了解的模块吧

第一章、各模块介绍

1、time模块——生成时间相关

import time
>>> res = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
>>> print(res)
2021-04-15 18:53:20

>>> res = time.strftime("%Y%m%d",time.localtime())
>>> print(res)
20210415

2、os模块的使用——创建目录

因为open模块只能创建文件,目录需要os模块来创建

import os
if not os.path.isdir("machine_learning"): 	#判定如何没有这个目录,就创建
    os.makedirs("machine_learning")			#创建

3、Netmiko-SSH巡检

通过ssh,巡检h3c的交换机。关键模块是ConnectHandler。

#!/usr/bin/python3
#H3c交换机
from netmiko import ConnectHandler

'''定义交换机,包括类型,密码,ip,主机名'''
ip_list = [
    ['交换机的sysname','交换机的管理ip'],
]

#这里定义了ssh要用到的参数
SW = {
    'device_type':'hp_comware',     #设备类型是netmiko预定义好的,现在用hp_comware是h3c的
    'username':'admin',				
    'ip':'',
    'password':"xxxxxx"
}
'''定义结束'''

'''交换机交互'''
for ip_item in ip_list:
    SW['ip'] = ip_item[1]
    connect = ConnectHandler(**SW)
    print(log_time + 'Successfully connected to ' + ip_item[0])
    output = connect.send_command('system view')
    iproute = connect.send_command("display ip routing-table")
   	print(output) 				#验证	
    print(iproute) 				#验证
'''交换结束'''

3.2、Netmiko-telnet巡检

telnet与ssh的区别应该就在于,device_type中尾部添加_telnet,用的是Netmiko,而ssh用的是ConnectHandler。

我们的telnet分为h3c和cisco。

H3C
from netmiko import Netmiko

'''定义交换机,包括类型,密码,ip,主机名'''
ip_list = [
    ['交换机的sysname','交换机的ip地址'],   #定义设备的用户名和管理地址
]
SW = {
    'device_type':'hp_comware_telnet',					#设备类型是netmiko预定义好的
    'username':'admin',
    'ip':'',
    'password':"xxxxxx",	
}
'''完成定义'''

'''与交换机交互'''
for ip_item in ip_list:
    SW['ip'] = ip_item[1]
    connect = Netmiko(**SW)
    print(log_time + 'Successfully connected to ' + ip_item[0])
    config = connect.send_command('dis cur')
    fan = connect.send_command('dis fan')
    print(config) 	#验证一下值是不是想要的
    print(fan) 		#验证一下值是不是想要的
cisco

主要的不同是,cisco的telnet是需要enable的。

from netmiko import Netmiko

'''定义交换机,包括类型,密码,ip,主机名'''
ip_list = [
    ['交换机的hostname','交换机的ip'],   #定义设备的用户名和管理地址
]
SW = {
    'device_type':'cisco_iso_telnet',					#设备类型是netmiko预定义好的
    'username':'admin',
    'ip':'',
    'password':"xxxxxx",								#telnet的密码
    'secret':'xxxxx',									#enable的密码
}
'''完成定义'''

'''与交换机交互'''
for ip_item in ip_list:
    SW['ip'] = ip_item[1]
    connect = Netmiko(**SW)
    connect.enable()									#注意这个地方!cisco是这样enable的
    print(log_time + 'Successfully connected to ' + ip_item[0])
    config = connect.send_command('shun run')
    cpu = connect.send_command('sh process cpu')
    print(config) 	#验证一下值是不是想要的
    print(fan) 		#验证一下值是不是想要的

4、xlwt模块-创建excel

import xlwt
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('巡检报告第一次') #创建worksheet
worksheet.write(0,0,label = '设备名称')			#对A1添加内容
worksheet.write(0,1,label = '属性')				#对B1添加内容
worksheet.write(0,2,'值')						#对C2添加内容
workbook.save('巡检报告生成.xls')					#保存到excel,如果没有会创建。

在这里插入图片描述

5、re模块——正则表达式,截取想要的字段。

截取a-b之间的字符串:不包括ab

#注意有两种形式。一个匹配到第一个b,一个是匹配到最后一个b。
import re
number = "a123b456b" 

print(re.findall(r"a(.+?)b", number)) #注意!匹配到第一个b。
#输出['123']

print(re.findall(r"a(.+)b", number)) #这个是匹配到最后一个b
#输出['123b456']

另外一种正则表达式的使用形式

import re
number = "a123b456b"

pattern = re.complie("a(.+)b")
print(pattern.findall(number))
#输出['123b456']

从a开始截取到b为止: 包括ab

import re
number = "a123b456b" 

print(re.findall(r"a.+?b", number)) #注意!匹配到第一个b。
#输出['a123b']

print(re.findall(r"a.+b", number)) #这个是匹配到最后一个b
#输出['a123b456b']

第二章、巡检脚本介绍

1、巡检并记录下txt

这里只自定义了一个h3c的交换机巡检模块,而cisco的大同小异,差别在于 ”使用不同的netmiko子模块“、“定义交换机时多一个enable密码”、”多了enable模块(在第一章—3.2——cisco中有说明))“

#!/usr/bin/python3
#H3c交换机
'''-------模块导入--------'''
import time
from netmiko import ConnectHandler
from netmiko import Netmiko
import os
import re
import xlwt
'''--------模块导入结束--------'''

'''----------------------创建文件夹-------------------------'''
time_str = time.strftime('%Y_%m_%d', time.localtime())
path = "D:\\Seafile\\2021年农林维护\\3-巡检"
title = "%s"%time_str
new_path = os.path.join(path, title) #创建基于日期命名的文件夹
log_path = "%s\\巡检文件"%new_path	
config_path = "%s\\配置文件备份"%new_path
if not os.path.isdir(new_path):
    os.makedirs(new_path)
if not os.path.isdir(log_path):
    os.makedirs(log_path)
if not os.path.isdir(config_path):
    os.makedirs(config_path)
'''----------------------------创建文件夹结束------------------'''

'''-------------------和学校h3c交换机交互,并保留文本用于后期筛选数据的模块-----------'''
def h3c_ssh_v7(sysname,ipadd):
    ip_list = [
        [sysname,ipadd],
    ]
    SW = {
        'device_type':'hp_comware',
        'username':'用户名',
        'ip':'',
        'password':"密码",
    }
    
    for ip_item in ip_list:
        SW['ip'] = ip_item[1]
        connect = ConnectHandler(**SW)
        print(time_str + 'Successfully connected to ' + ip_item[0])
        config = connect.send_command('dis current-configuration')
        fan = connect.send_command('dis fan')
        
        '''-----这里我们只需要dis process cpu第一行的资料,进行预筛查----'''
        cpu = connect.send_command('dis process cpu')
        cpu = cpu.split('\n')	#cpu show出来时纯字符串,我用split配合换行符分割。
        cpu = cpu[0]			#分割好只取第一行
        '''-----------------------cpu内容预筛选结束-------------------'''
        
        power = connect.send_command('dis power')
        manager_ip = connect.send_command('dis ip int vlan 1 brief')
        device = connect.send_command('dis device | exclude NONE')
        
        '''-------------------同样时预筛查只需要前四行内容-----------------------'''
        version = connect.send_command('dis version')
        version = version.split('\n')
        version = '\n'.join(version[0:4]) #因为version[0:4]出来的是一个列表,所以使用join,将列表内容拼接成字符串。
        '''-------------------------预筛查结束--------------------------------'''
    
        config_fo = open('%s\\%s-%s_config.txt'%(config_path,ip_item[0],ip_item[1]),'w',encoding='utf-8')#创建配置备份,文件名时sysname-ipadd的格式。记住这里一定要加入encoding=‘utf-8',不然有些h3c设备可能会报错。
        fo = open('%s\\%s-%s.txt'%(log_path,ip_item[0],ip_item[1]),'w') #创建巡检的文件。存放巡检时候产生的数据
        config_fo.write(config)
        if cpu:									#如果cpu有数据存在
            fo.write(cpu)						#把cpu的巡检结果写入巡检文件 以下类似
        fo.write('\n')							#换行,让文本看的清楚些用的。以下大概就这些消息,不逐一说了
        fo.write('\n')
        if fan:
            fo.write(fan)
        fo.write('\n')
        fo.write('\n')
        if power:
            fo.write(power)
        fo.write('\n')
        fo.write('\n')
        if version:
            fo.write(version)
        fo.write('\n')
        fo.write('\n')
        if manager_ip:
            fo.write(manager_ip)
        fo.write('\n')
        fo.write('\n')
        if device:
            fo.write(device)
            
h3c_ssh_v7('设备的sysname','设备的ip地址')记得调用函数
"""------------------------------------巡检备份结束-------------------------------------------------------"""

2、分析文件并写入excel报告

因为楼宇,核心,服务器核心所生成的巡检文件有很大的不同所以我选择了分开写。

这里我只列了我们核心交换机的数据抓取。

"""-------------------承接上面的代码(因为要用到导入的模块和变量))---生成报告-------------------------------"""
y = 1 #这个是用来记录我的excel写到了哪一行的
def h3c_core_report(hostname,ipadd):
        file = open('%s\\%s-%s.txt'%(log_path,hostname,ipadd))
        listlist=file.readlines()
        i=1 #注意:在下面'''分析提取数据并提取'''代码块最后有个i += 1 用于计数。当“我要抓取的数据在我能匹配到数据行的下一行。”的时候就会用到了。
       
        
'''------------------------分析数据并提取--------------------------------------------'''
        for line in listlist:
            if 'CPU utilization' in line:
                    pattern = re.compile('5.+%')	#正则匹配的匹配规则
                    cpu_use_list = pattern.findall(line) #使用规则抓出数据,下面的代码都是大同小异的抓取
                    for cpu_use in cpu_use_list:    #因为抓出的数据是列表,用for循环转换为字符。其实可以用cpu_use_list[0]。
                            print(cpu_use)
            if 'weeks' in line:
                    run_time_list = re.findall("uptime is(.+?)\n",line)
                    for run_time in run_time_list:
                            print(run_time.strip())
            if 'Chassis 1' in line:     #因为用了H3C的IRF设备,有多行Chassis 1,显示chassis1上例如风扇、电源的状态
                    if 'Fan' in listlist[i]: #和上一行执行“与”操作,匹配到就抓取数据。
                            pattern = re.compile(':(.+)\n')
                            chassis_1_fan_list = pattern.findall(listlist[i]) #这个就是抓取匹配行的下一行
                            for chassis_1_fan in chassis_1_fan_list:
                                    chassis_1_fan = chassis_1_fan.strip()
                                    print(chassis_1_fan)
                    if 'Power' in listlist[i]: #和chassis 1行进行“与”操作,匹配就抓取需要的数据
                            pattern = re.compile(':(.+)\n')
                            chassis_1_power_0_state_list = pattern.findall(listlist[i])
                            for chassis_1_power_0_state in chassis_1_power_0_state_list:
                                    chassis_1_power_0_state = chassis_1_power_0_state.strip()
                                    print(chassis_1_power_0_state)

                            chassis_1_power_1_state_list = pattern.findall(listlist[i+1])
                            for chassis_1_power_1_state in chassis_1_power_1_state_list:
                                    chassis_1_power_1_state = chassis_1_power_1_state.strip()
                                    print(chassis_1_power_1_state)
                                    
                            chassis_1_power_2_state_list = pattern.findall(listlist[i+2])
                            for chassis_1_power_2_state in chassis_1_power_2_state_list:
                                    chassis_1_power_2_state = chassis_1_power_2_state.strip()
                                    print(chassis_1_power_2_state)
                                    
                            chassis_1_power_3_state_list = pattern.findall(listlist[i+3])
                            for chassis_1_power_3_state in chassis_1_power_3_state_list:
                                    chassis_1_power_3_state = chassis_1_power_3_state.strip()
                                    print(chassis_1_power_3_state)
                                    
                            chassis_1_power_4_state_list = pattern.findall(listlist[i+4])
                            for chassis_1_power_4_state in chassis_1_power_4_state_list:
                                    chassis_1_power_4_state = chassis_1_power_4_state.strip()
                                    print(chassis_1_power_4_state)

                            chassis_1_power_5_state_list = pattern.findall(listlist[i+5])
                            for chassis_1_power_5_state in chassis_1_power_5_state_list:
                                    chassis_1_power_5_state = chassis_1_power_5_state.strip()
                                    print(chassis_1_power_5_state)

            if 'Chassis 2' in line: #这里就是抓取chassis 2上的数据
                    if 'Fan' in listlist[i]:
                            pattern = re.compile(':(.+)\n')
                            chassis_2_fan_list = pattern.findall(listlist[i])
                            for chassis_2_fan in chassis_2_fan_list:
                                    chassis_2_fan = chassis_2_fan.strip()
                                    print(chassis_2_fan)
                    if 'Power' in listlist[i]:
                            pattern = re.compile(':(.+)\n')
                            chassis_2_power_0_state_list = pattern.findall(listlist[i])
                            for chassis_2_power_0_state in chassis_2_power_0_state_list:
                                    chassis_2_power_0_state = chassis_2_power_0_state.strip()
                                    print(chassis_2_power_0_state)

                            chassis_2_power_1_state_list = pattern.findall(listlist[i+1])
                            for chassis_2_power_1_state in chassis_2_power_1_state_list:
                                    chassis_2_power_1_state = chassis_2_power_1_state.strip()
                                    print(chassis_2_power_1_state)
                                    
                            chassis_2_power_2_state_list = pattern.findall(listlist[i+2])
                            for chassis_2_power_2_state in chassis_2_power_2_state_list:
                                    chassis_2_power_2_state = chassis_2_power_2_state.strip()
                                    print(chassis_2_power_2_state)
                                    
                            chassis_2_power_3_state_list = pattern.findall(listlist[i+3])
                            for chassis_2_power_3_state in chassis_2_power_3_state_list:
                                    chassis_2_power_3_state = chassis_2_power_3_state.strip()
                                    print(chassis_2_power_3_state)
                                    
                            chassis_2_power_4_state_list = pattern.findall(listlist[i+4])
                            for chassis_2_power_4_state in chassis_2_power_4_state_list:
                                    chassis_2_power_4_state = chassis_2_power_4_state.strip()
                                    print(chassis_2_power_4_state)

                            chassis_2_power_5_state_list = pattern.findall(listlist[i+5])
                            for chassis_2_power_5_state in chassis_2_power_5_state_list:
                                    chassis_2_power_5_state = chassis_2_power_5_state.strip()
                                    print(chassis_2_power_5_state)

            if '1/0' in line: #抓取板卡信息
                    slot1_1_list = line.split()  #为了抓取状态值使用的手段,主要是将字段转成列表,然后再提取列表中的字符,以下其他板卡形式相同。
                    slot1_1_state = slot1_1_list[2]
                    print(f"1{slot1_1_state}")
            if '1/4    LSUM1SUPC0' in line:
                    slot1_4_list = line.split()
                    slot1_4_state = slot1_4_list[2]
                    print(f"4{slot1_1_state}")
            if '1/5    LSUM1SUPC0' in line:
                    slot1_5_list = line.split()
                    slot1_5_state = slot1_5_list[2]
                    print(slot1_5_state)
            if '1/7    LSUM2TGS16SF0' in line:
                    slot1_7_list = line.split()
                    slot1_7_state = slot1_7_list[2]
                    print(slot1_7_state)
            if '1/9    LSUM2GT24PTSSE0' in line:
                    slot1_9_list = line.split()
                    slot1_9_state = slot1_9_list[2]
                    print(slot1_9_state)
            if '1/10   LSU1FAB08B0' in line:
                    slot1_10_list = line.split()
                    slot1_10_state = slot1_10_list[2]
                    print(f"10{slot1_10_state}")
            if '1/11   LSU1FAB08B0' in line:
                    slot1_11_list = line.split()
                    slot1_11_state = slot1_11_list[2]
                    print(slot1_11_state)
            if '1/12   LSU1FAB08B0' in line:
                    slot1_12_list = line.split()
                    slot1_12_state = slot1_12_list[2]
                    print(slot1_12_state)
            if '1/13   LSU1FAB08B0' in line:
                    slot1_13_list = line.split()
                    slot1_13_state = slot1_13_list[2]
                    print(slot1_13_state)

            if '2/0    LSUM2GT48SE0' in line:
                    slot2_1_list = line.split()
                    slot2_1_state = slot2_1_list[2]
                    print(slot2_1_state)
            if '2/4    LSUM1SUPC0' in line:
                    slot2_4_list = line.split()
                    slot2_4_state = slot2_4_list[2]
                    print(slot2_4_state)
            if '2/5    LSUM1SUPC0' in line:
                    slot2_5_list = line.split()
                    slot2_5_state = slot2_5_list[2]
                    print(slot2_5_state)
            if '2/7    LSUM2TGS16SF0' in line:
                    slot2_7_list = line.split()
                    slot2_7_state = slot2_7_list[2]
                    print(slot2_7_state)
            if '2/9    LSUM2GT24PTSSE0' in line:
                    slot2_9_list = line.split()
                    slot2_9_state = slot2_9_list[2]
                    print(slot2_9_state)
            if '2/10   LSU1FAB08B0' in line:
                    slot2_10_list = line.split()
                    slot2_10_state = slot2_10_list[2]
                    print(slot2_10_state)
            if '2/11   LSU1FAB08B0' in line:
                    slot2_11_list = line.split()
                    slot2_11_state = slot2_11_list[2]
                    print(slot2_11_state)
            if '2/12   LSU1FAB08B0' in line:
                    slot2_12_list = line.split()
                    slot2_12_state = slot2_12_list[2]
                    print(slot2_12_state)
            if '2/13   LSU1FAB08B0' in line:
                    slot2_13_list = line.split()
                    slot2_13_state = slot2_13_list[2]
                    print(slot2_13_state)


            i += 1 #用来计数的。
'''-------------------------分析和提取数据结束----------------------------------'''

'''-----------------------开始写入excle数据------------------------------------'''
        x = 0    #用来计算我这个交换机用了多少行。主要为合并单元格服务的
        global y #计算整个excel使用了多少行。主要帮助程序从那里一行开始写入,合并单元格的时候也会用到。
        worksheet.write(y,1,label = '管理地址')
        worksheet.write(y,2,label = ipadd)
        y = y + 1
        x += 1
        if cpu_use:
                worksheet.write(y,1,label = 'CPU使用率')
                worksheet.write(y,2,cpu_use)
                y = y + 1
                x += 1
        if run_time:
                worksheet.write(y,1,label = '运行时间')
                worksheet.write(y,2,run_time)
                y = y + 1
                x += 1
        if slot1_1_state:
                worksheet.write(y,1,"slot1_1")
                worksheet.write(y,2,slot1_1_state)
                y = y + 1
                x += 1
        if slot1_4_state:
                worksheet.write(y,1,"slot1_4")
                worksheet.write(y,2,slot1_4_state)
                y = y + 1
                x += 1
        if slot1_5_state:
                worksheet.write(y,1,"slot1_5")
                worksheet.write(y,2,slot1_5_state)
                y = y + 1
                x += 1
        if slot1_7_state:
                worksheet.write(y,1,"slot1_7")
                worksheet.write(y,2,slot1_7_state)
                y = y + 1
                x += 1
        if slot1_9_state:
                worksheet.write(y,1,"slot1_9")
                worksheet.write(y,2,slot1_9_state)
                y = y + 1
                x += 1
        if slot1_10_state:
                worksheet.write(y,1,"slot1_10")
                worksheet.write(y,2,slot1_10_state)
                y = y + 1
                x += 1
        if slot1_11_state:
                worksheet.write(y,1,"slot1_11")
                worksheet.write(y,2,slot1_11_state)
                y = y + 1
                x += 1
        if slot1_12_state:
                worksheet.write(y,1,"slot1_12")
                worksheet.write(y,2,slot1_12_state)
                y = y + 1
                x += 1
        if slot1_13_state:
                worksheet.write(y,1,"slot1_12")
                worksheet.write(y,2,slot1_13_state)
                y = y + 1
                x += 1
        if slot1_1_state:
                worksheet.write(y,1,"slot1_1")
                worksheet.write(y,2,slot1_1_state)
                y = y + 1
                x += 1
        if slot1_4_state:
                worksheet.write(y,1,"slot1_4")
                worksheet.write(y,2,slot1_4_state)
                y = y + 1
                x += 1
        if slot1_5_state:
                worksheet.write(y,1,"slot1_5")
                worksheet.write(y,2,slot1_5_state)
                y = y + 1
                x += 1
        if slot1_7_state:
                worksheet.write(y,1,"slot1_7")
                worksheet.write(y,2,slot1_7_state)
                y = y + 1
                x += 1
        if slot1_9_state:
                worksheet.write(y,1,"slot1_9")
                worksheet.write(y,2,slot1_9_state)
                y = y + 1
                x += 1
        if slot1_10_state:
                worksheet.write(y,1,"slot1_10")
                worksheet.write(y,2,slot1_10_state)
                y = y + 1
                x += 1
        if slot1_11_state:
                worksheet.write(y,1,"slot1_11")
                worksheet.write(y,2,slot1_11_state)
                y = y + 1
                x += 1
        if slot1_12_state:
                worksheet.write(y,1,"slot1_12")
                worksheet.write(y,2,slot1_12_state)
                y = y + 1
                x += 1
        if slot1_13_state:
                worksheet.write(y,1,"slot1_12")
                worksheet.write(y,2,slot1_13_state)
                y = y + 1
                x += 1
        worksheet.write_merge(y-x,y-1,0,0,hostname)
        workbook.save('%s\\巡检报告生成.xls'%(log_path))
        print(y)         
        print(x)
"""-------------------------------------------写入结束--------------------------------------------------"""
        
h3c_core_report('Dh_Tsg_1F_HeXin_S10508-V','10.27.0.1') #记得调用函数。
"""------------------------------------生成报告完成-------------------------------------------------------"""

脚本执行后的结果:

将上述的代码合并,在计算机任意位置执行,它就会自动生成一系列我们需要的文件。

excel巡检报告结果如图:此图我还是手动调整过的,因为在生成excel的时候没有,我没有定义style文件(因为懒),但是具体xwlt是可以实现的。
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐