H3C_Python_SSH_Config_Auto

  • Python 脚本 SSH 登陆华三设备,使用定义好的 display 脚本批量导出配置和一些设备状态
  • Python 脚本 SSH 登陆华三设备,使用定义好的配置命令批量增加配置
  • 主要使用的是 netmiko 这个模块里的 ConnectHandler 命令
  • 单线程
  • 脚本运行完成后输出 成功和失败的记录log
  • ip_list.txt,cmd_list.txt,cmd_config_list.txt 格式简单,修改方便
  • 未做多账号密码的 if 语句判断
  • 肯定有冗余繁重的代码

脚本文件

py01.py


import time
from netmiko import ConnectHandler, NetMikoAuthenticationException, NetMikoTimeoutException
import os
import re

time_str1 = time.strftime('%Y_%m_%d', time.localtime())
time_str2 = time.strftime('%H%M%S', time.localtime())
time_str3 = time.strftime('%H:%M:%S', time.localtime())
path = "F:\\XXXXX\\py_net"
title = "%s" % time_str1
# mkdir path & touch file
new_path = os.path.join(path, title)
config_path = "%s\\configuration_backup" % new_path
if not os.path.isdir(new_path):
    os.makedirs(new_path)
if not os.path.isdir(config_path):
    os.makedirs(config_path)
# 创建日志文件,记录运行结果
log_fo = open('%s\\%s.log' % (config_path, time_str1), 'a+',
              encoding='utf-8')
log_fo.write('\n' + "==========START TIME " + time_str3 + "=========" + '\n')
# 读取 ip_list.txt 里的 ip 地址
ip_list = open('ip_list.txt', 'r', encoding='ascii')
ip_addr = ip_list.readlines()
ip_list.close()
# display 命令
cmd_list = open('cmd_list.txt', 'r', encoding='ascii')
cmd_line = cmd_list.readlines()
cmd_list.close()

# 遍历 ip_addr 列表里面的 ip 进行连接
for ip in iter(ip_addr):
    try:
        S5130 = {
            'device_type': 'hp_comware',
            'ip': ip,
            'username': 'admin',
            'password': 'xxxxxxxxxx',
        }

        net_connect = ConnectHandler(**S5130)
        # 禁用输出屏幕分屏
        screen_d = net_connect.send_command('screen-length disable')
        # current_time as part of filename
        time_str2 = time.strftime('%H%M%S', time.localtime())
        # sysname as part of fielname
        sysn = net_connect.send_command('dis cur | inc sysname')
        # split 空格分割回显内容
        sysn = re.split(r'[ ]+', sysn)
        sysn = sysn[2]
        # 创建文件, 格式为 sysname + time_str2
        config_fo = open('%s\\%s_%s_config.txt' % (config_path, sysn, time_str2), 'a',
                         encoding='utf-8')
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        print(time_str1 + "_" + time_str3 + ' Successfully connected to ' + ip)
        log_fo.write(time_str1 + "_" + time_str3 + ' Successfully connected to ' + ip)
        for cmd in iter(cmd_line):
            cmd_result = net_connect.send_command(cmd)
            print(cmd)
            print(cmd_result)
            print('===================================================================')
            config_fo.write('\n'
                            + '==================================================================='
                            + '\n'
                            + cmd
                            + '\n'
                            + cmd_result)
        net_connect.disconnect()
        config_fo.close()
    except (EOFError, NetMikoTimeoutException):
        print('Can not connect to Device ' + ip)
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        log_fo.write(time_str1 + "_" + time_str3 + ' Can not connect to Device ' + ip)
    except (EOFError, NetMikoAuthenticationException):
        print('username/password wrong! ' + ip)
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        log_fo.write(time_str1 + "_" + time_str3 + ' username/password wrong! ' + ip)
time_str4 = time.strftime('%H:%M:%S', time.localtime())
log_fo.write('\n' + "==========END TIME " + time_str4 + "==========" + '\n')
log_fo.close()
print(log_fo)

py02.py


import time
from netmiko import ConnectHandler, NetMikoAuthenticationException, NetMikoTimeoutException
import os
import re

time_str1 = time.strftime('%Y_%m_%d', time.localtime())
time_str2 = time.strftime('%H%M%S', time.localtime())
time_str3 = time.strftime('%H:%M:%S', time.localtime())
path = "F:\\XXXXX\\py_net"
title = "%s" % time_str1
# mkdir file & touch file
new_path = os.path.join(path, title)
config_path = "%s\\configure_device" % new_path
if not os.path.isdir(new_path):
    os.makedirs(new_path)
if not os.path.isdir(config_path):
    os.makedirs(config_path)
# 创建日志文件,记录运行结果
log_fo = open('%s\\%s.log' % (config_path, time_str1), 'a+',
              encoding='utf-8')
log_fo.write('\n' + "==========START TIME " + time_str3 + "=========" + '\n')
# 读取 ip_list.txt 里的 ip 地址
ip_list = open('ip_list.txt', 'r', encoding='ascii')
ip_addr = ip_list.readlines()
ip_list.close()
# 读取 cmd_config_list.txt 文件的配置命令
cmd_config_list = open('cmd_config_list.txt', 'r', encoding='ascii')
cmd_line = cmd_config_list.readlines()
print(cmd_line)
cmd_config_list.close()

# 遍历 ip_addr 列表里面的 ip 进行连接
for ip in iter(ip_addr):
    try:
        S5130 = {
            'device_type': 'hp_comware',
            'ip': ip,
            'username': 'admin',
            'password': 'xxxxxxxxxx',
        }

        net_connect = ConnectHandler(**S5130)
        # 禁用输出屏幕分屏
        screen_d = net_connect.send_command('screen-length disable')
        # current_time as part of filename
        time_str2 = time.strftime('%H%M%S', time.localtime())
        # sysname as part of fielname
        sysn = net_connect.send_command('dis cur | inc sysname')
        # split 空格分割回显内容
        sysn = re.split(r"[ ]+", sysn)
        sysn = sysn[2]
        # 创建文件, 格式为 sysname + time_str2
        config_fo = open('%s\\%s_%s_add_config.txt' % (config_path, sysn, time_str2), 'a',
                         encoding='utf-8')
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        print(time_str1 + "_" + time_str3 + ' Successfully connected to ' + ip + ' Configuring...')
        log_fo.write(time_str1 + "_" + time_str3 + ' Configuration complete: ' + ' Successfully connected to ' + ip)
        cmd_result = net_connect.send_config_set(cmd_line)
        print(cmd_result)
        print('===================================================================')
        config_fo.write('\n'
                        + '==================================================================='
                        + '\n'
                        + cmd_result)
        net_connect.disconnect()
        config_fo.close()
    except (EOFError, NetMikoTimeoutException):
        print('Can not connect to Device ' + ip)
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        log_fo.write(time_str1 + "_" + time_str3 + ' Configuration Fail: ' + ' Can not connect to Device! ' + ip)
    except (EOFError, NetMikoAuthenticationException):
        print('username/password wrong! ' + ip)
        time_str3 = time.strftime('%H:%M:%S', time.localtime())
        log_fo.write(time_str1 + "_" + time_str3 + ' Configuration Fail: ' + ' username/password wrong! ' + ip)
time_str4 = time.strftime('%H:%M:%S', time.localtime())
log_fo.write('\n' + "==========END TIME " + time_str4 + "==========" + '\n')
log_fo.close()
print(log_fo)

运行环境

  1. Python3,理论上 Python3 版本都可运行,没看到新版本更新日志说哪里有变动
    • 在 win7 系统 3.8.10 版本运行测试无问题
    • 在 win10 系统 3.9.7 版本运行测试无问题
    • 在 win10 系统 3.10.4 版本运行测试无问题
  2. 安装 netmiko
  3. 测试连接 HCL_Setup_V3.0.1 模拟器设备无问题
  4. 测试连接真实 H3C 设备,无问题
  5. 运行速度取决与设备的连接反应和脚本行数

三个文件

ip_list.txt (faker)

10.1.1.1
10.1.1.2
10.1.1.3
10.1.1.4
10.1.1.5

cmd_list.txt (faker)

display cur 
display ip interface brief
display interface brief des
display vlan
display vlan brief
display ip routing-table
display version
display cpu-usage
display memory
display power
display fan
display device manuinfo
display device verbose 
display environment
dir
display irf
display irf configuration
display irf link 
display irf topology
display link-aggregation summary
display link-aggregation member-port 
display link-aggregation verbose 
display current-configuration configuration system
display boot-loader
save force
#

cmd_config_list.txt (faker)

vlan 22
des MMT22
dis th
int vlan 22
des MMT22
ip add 192.168.22.22 24
dis th

运行过程

  • py01.py 运行结束后会在 本 py01.py 文件所在的目录创建一个名为 20xx_xx_xx (运行此脚本当日年月日)的文件夹

  • py02.py 运行结束后会在 本 py02.py 文件所在的目录创建一个名为 20xx_xx_xx(运行此脚本当日年月日) 的文件夹

  • 以上创建的文件夹,脚本会判断是否存在,如存在则跳过;不存在则创建

  • 假设已经各运行完成一次以上两个脚本,则名为 20xx_xx_xx 的文件夹下会创建 “configuration_backup” 和 “configure_device”两个文件夹

    • configuration_backup 保存导出的配置和一些设备状态信息

    • configure_device 保存批量增加配置的记录过程

  • “configuration_backup” 和 “configure_device”两个文件夹下,会生成文件名称为 “ 20xx_xx_xx.log”(当天日期)的文件,用来记录执行成功和执行失败的log

  • “configuration_backup” 和 “configure_device”两个文件夹下,有文件名称为 “sysname + time_str2_config.txt” (设备名+创建时间)的 TXT 文件,或 “sysname + time_str2_add_config.txt” (设备名+创建时间)的 TXT 文件

参考资料:

- Python-交换机自动化巡检脚本笔记 by 02EVA on 2021-04-22 : https://blog.csdn.net/weixin_42065669/article/details/116009445
-「Python 网络自动化」Netmiko ——Netmiko 常用方法 by 某呆啊 on 2021-02-04 : https://blog.csdn.net/q965844841qq/article/details/113619281
- Python 逐行读取txt 文件并生成列表 by 诺亚方包 on 2020-05-19 : https://blog.csdn.net/weixin_40973138/article/details/106209020
- Python 使用 Netmiko 连接 H3C 网络设备 by 某呆 on 2021-02-03  : https://555.xdai.vip/posts/26e9de3c.html
- H3C交换机python命令下发脚本 by xuwenfang1989 on 2018-08-27 : https://blog.51cto.com/u_1339643/2164819