通过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)
=======================脚本到此结束===================================
2170





