通过Python3脚本实现设备的自动化配置备份,设计版本为EVE-NG华为的模拟器终端。
需求:
1、备份目录要清晰规整,方便查询。
2、设备信息和命令信息可以定制化,并且能检测命令是否存在,并给出解决提示。
2、备份网络中的网络设备,需要对设备登陆信息和失败信息进行记录。
3、备份的数据要注明设备名称和管理地址以及配置备份的时间,精确到分钟。
4、备份完成后还要统计完成情况并反馈。
5、没有备份成功的设备要抛出报错信息,方便管理员修正。
设计思路:
需求想目录清晰,那就必须要根据需求完成目录以及文件的检测,并尽可能的自动化处理问题,如果不能自动化处理的,需要给出提示,需要通过判断来完成这些情况。在远程管理设备这个过程中,需要使用到netmiko和paramiko,根据自己的需求选择,我这里为了简单,选择了netmiko。需需求中还需要解决设备备份成功和失败的记录,并且成功记录要以固定的名称格式存储,并且还要记录成功结果和失败信息,这里就需要深入了解netmiko的报错信息以及通过字Python内置函数和字符串拼接的方式,完成上述功能。
好了,废话到此结束,上脚本,希望能给各位初学者一些帮助。
=======================脚本到此开始===================================
#!/usr/bin/python3.8 # -*- coding=utf-8 -*- # 脚本由Fly编写 # QQ:420282316 # https://gitee.com/LuckFly import sys import netmiko from netmiko import ConnectHandler import time from datetime import datetime import re import os from getpass import getpass import threading #创建配置文件保存目录函数 def create_folder (folder_name): folder = os.path.exists(folder_name) if not folder: os.mkdir(folder_name) print("创建目录完成,目录路径为:"+ str(folder_name)) else: print('目录已经存在,请检查'+ str(folder_name)+'!删除后重试!') sys.exit(0) #无法创建保存路径,退出程序 #备份配置并存入硬盘函数 def netmiko_devices_backtodisk(device_type,ip,username,password): #创建远程登录信息库 swx = { 'device_type':device_type, 'ip':ip, 'username':username, 'password':password, 'conn_timeout': 3, #连接超时时间 } #创建日志文件 lp = open('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_pass.txt','w') lp.close() lf = open('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt','w') lf.close() #运行远程登录函数进行远程登录设备,如果登陆成功则打印出登陆成功的信息和IP try: connect_device = ConnectHandler(**swx) #尝试登陆设备 if connect_device: #判断登陆是否成功 print(swx['ip']+'登陆成功!') #根据设备类型选择对应的命令文件,此处有多少设备类型就创建多少行IF命令,需要注意的是,因设备类型关乎netmiko登陆设备,故需要参考netmiko的厂商类型定义设备类型关键词 if device_type == 'huawei': if os.path.exists('E:/交换机配置备份/devices_command/huawei-commands.txt'): device_type_command_file = 'devices_command/huawei-commands.txt' device_n = connect_device.send_command('display current-configuration | include sysname') #读取设备名称 device_name = re.search(r'sysname (\w+.\w+|\w+)',device_n).groups()[0]#获取设备名称 else: print('E:/交换机配置备份/devices_command/huawei-commands.txt,不存在,请创建!') print(''' huawei-commands.txt 格式: display current-configuration ....... ''') sys.exit() if device_name: #判断设备名是否存在 #print('采集'+str(device_name)+'完成!准备写入!') datetimenow = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") #格式化是时间 else: print('获取设备名失败,请检查程序!') sys.exit() device_config_name = device_name+ "_"+ swx['ip'] + "_" + datetimenow + '.txt' #创建备份文件的文件名 #打开命令文件并执行,读取返回结果 #print(str(device_name)+'正在写入!') commands_file = open('E:/交换机配置备份/'+device_type_command_file , 'r',encoding='UTF-8') for device_commands in commands_file: devices_config = connect_device.send_command(device_commands) #开始读取配置 time.sleep(1) #休眠2秒,防止配置读取不全 writefile = open('E:/交换机配置备份/'+folder_name+'/'+device_config_name, 'a') try: #写入时确认写入的编码格式 writefile.write(devices_config.decode(encoding='utf-8')) except: try: writefile.write(devices_config.decode(encoding='gbk')) except: writefile.write(str(devices_config)) writefile.close() #关闭读取文件 commands_file.close() #关闭命令文件 pass_device = (swx['ip']+"登陆成功!,并完成了配置备份。") #确认登陆成功 #打开登陆成功的日志文件,写入日志。 login_pass = open(f'E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_pass.txt', 'a') login_pass.write(pass_device+'\n') login_pass.close() print(str(device_name)+'写入完成!') print('==========================================================') except netmiko.exceptions.NetmikoAuthenticationException: #如果登陆失败,写入失败日志 fail_devices = (swx['ip']+'用户名密码是否正确!') login_failds = open(f'E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt', 'a') login_failds.write(fail_devices+'\n') login_failds.close() except netmiko.exceptions.NetmikoTimeoutException: #如果登陆失败,写入失败日志 fail_devices = (swx['ip']+'地址不可达!') login_failds = open(f'E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt', 'a') login_failds.write(fail_devices+'\n') login_failds.close() time.sleep(3) #以下是主代码 if __name__ == '__main__': print('欢迎使用DCI网络自动化运维系统-自动化配置备份模块!') print('正在检查相关目录文件是否存在,请稍后……') if not os.path.exists('E:/交换机配置备份/devices_command/'): print('设备配置命令目录不存在,请创建:E:/交换机配置备份/devices_command/,并创建huawei-commands.txt供程序使用!') print(''' huawei-commands.txt 格式: display current-configuration ....... ''') sys.exit() if not os.path.exists('E:/交换机配置备份/log_file/'): print('检测E:/交换机配置备份/log_file/目录不存在,正在创建!') os.mkdir('E:/交换机配置备份/log_file/') print('E:/交换机配置备份/log_file/目录,创建完成!') username = input('请输入备份配置所需的远程管理用户名:') #password = getpass('请输入配置所需的远程管理密码:') password = input('请输入配置所需的远程管理密码:') print('正在创建备份文件的文件夹,请稍后……') #定义备份文件目录的名称并创建目录 folder_name = time.strftime("%Y-%m-%d", time.localtime()) create_folder(f'E:/交换机配置备份/'+folder_name) #创建所需变量集字典 devices_list = {} # 设备文件,包括设备名和IP #判断设备列表文件是否存在,并写入字典后循环开始执行 if os.path.exists('E:/交换机配置备份/device_list/device_ipaddress.txt'): deviceip = open('E:/交换机配置备份/device_list/device_ipaddress.txt','r',encoding='UTF-8') for line in deviceip: line = line.strip().split(",") #以逗号分隔字符串 devices_list[line[0]] = line[:] #以设备名为字典的key,所有数据为key值 deviceip.close() for i in devices_list: threadtest = threading.Thread(name='t1',target=netmiko_devices_backtodisk,args=(devices_list[i][1],devices_list[i][0],username,password)) threadtest.start() #netmiko_devices_backtodisk(devices_list[i][1],devices_list[i][0],username,password) else: print('E:/交换机配置备份/device_list/device_ipaddress.txt,不存在,请检查目录是否正确') print(''' device_ipaddress.txt 格式如下: 172.16.254.11,huawei ......... ''') sys.exit() time.sleep(10) #如果这里的睡眠时间不够,会出现登陆设备超时导致的设备失败日志无法记录,计数失败。 print('正在统计备份情况,请稍后……') #尝试打开文件进行统计登陆成功 over_devices_num = 0 with open('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_pass.txt') as over_f: over_devices = over_f.readlines() #一行行读取 over_devices_num = len(over_devices) #判断有多少行 over_f.close() faild_devices_num = 0 with open('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt') as faild_f: faild_devices = faild_f.readlines() faild_devices_num = len(faild_devices) faild_f.close() huawei_devices_num = 0 huawei_devices = open('E:/交换机配置备份/device_list/device_ipaddress.txt','r',encoding='UTF-8') for huawei_i in huawei_devices: if 'huawei' in huawei_i: huawei_devices_num = huawei_devices_num + 1 huawei_devices.close() time.sleep(3) print('全部设备备份完毕!共计备份成功设备:'+str(over_devices_num)+'台,备份失败设备:'+str(faild_devices_num)+'台,其中华为设备:'+str(huawei_devices_num)+'台!') print('====================备份失败的设备列表=========================') faild_device_brief = "" if os.path.exists('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt'): login_failds_file = open('E:/交换机配置备份/log_file/'+ datetime.now().strftime('%Y%m%d') + '-login_failds.txt') for faild_x in login_failds_file: faild_device_brief += faild_x login_failds_file.close() print(faild_device_brief) else: print('没有备份失败的设备!') print('====================备份成功的设备列表=========================') over_devices_brief = "" login_pass_file = os.listdir(os.chdir('E:/交换机配置备份/'+folder_name)) for over_x in login_pass_file: over_devices_brief += over_x over_devices_brief += '\n' print(over_devices_brief)
=======================脚本到此结束===================================