1.背景介绍

     因日常运维需求需要收集配置和接口信息,用于配置备份和审计要求,以及机房搬迁、数据治理等原因需要配置信息收集; 配置采集需每天都要处理,且登陆网络设备的操作命令基本一致,且重复操作次数明显超过3次,考虑对接标准化和自动化操作; 标准化:不同品牌、不同类型的设备进行分组分类,按类别整理出标准化流程后,开始对其自动化;

2.模拟环境

本次模拟环境是华为模拟器ENSP,设备是CE6800(请注意,配置命令后要commit生效),IP地址已标注在图上; 拓扑如下图所示: image.png

2.1 配置接口IP地址

在CE1-CE3配置接口IP地址,以CE1为例子 interface GE1/0/0 undo portswitch undo shutdown ip address 192.168.58.202 255.255.255.0 生产环境中,需要敬畏之心,再小的操作(变更操作),均要验证,输出的命令是否符合预期; image.png CE1-CE3配置完成后,在CE1进行ping测试,可以验证出互通性和配置是否正确以及是否产生意料之外的问题(生产环境会有奇奇怪怪的问题,软件或硬件都可能会出现bug); image.png

2.2 配置SSH登陆

2.2.1 配置VTY用户界面

user-interface vty 0 4 authentication-mode aaa protocol inbound ssh

2.2.2 配置AAA认证

用户名和密码需要记录好,模拟环境使用弱口令密码,实际请使用复杂密码; aaa local-user admin@123 password irreversible-cipher 123456789 local-user admin@123 service-type ssh local-user admin@123 level 3   华为交换机基于安全考虑,默认开启本地账户安全策略功能,用户第一次登录时会被要求更改密码。 如果配置了下次登录提醒修改原始密码功能,用户登录也会提醒更改密码,实际使用过程比较麻烦,可以按需取消第一次登录更改密码的询问。 【题外话:安全是平衡的艺术,业务盈利、运维效率、数据安全三者求平衡】 undo local-user policy security-enhance undo local-user policy password change

2.2.3 配置SSH用户

stelnet server enable ssh user admin@123 ssh user admin@123 authentication-type password ssh user admin@123 service-type all ssh authorization-type default aaa

2.2.4 配置SSH登陆验证

做变更要严格按照SOP执行,一定要做变更验证,变更做完不是结束,验证完成才算。 image.png

3.批量登陆脚本

3.1 设备清单表样式

  模拟环境仅作演示,密码记录表格,实际情况是禁止在本地保存明文用户和密码; image.png

3.2 脚本逻辑

1)读取设备清单表,获取表头信息和每一行数据,将表头作为键,行数据作为值形成字典,见示例1;每个字典添加到列表中,见示例2; 示例1:{'设备登陆IP': '192.168.58.200'} 示例2:[{'设备登陆IP': '192.168.58.200'}, {'设备登陆IP': '192.168.58.201'}] 2)根据获取的登陆信息,登陆每台设备;成功和失败没有写入文件,只在程序页面打印,后续优化为输出记录文件; 3)执行输入的命令获取设备输出信息,直接打印获取信息,后续可以写入文件进行持久化保存;

3.3 脚本代码清单

import time
import openpyxl
import paramiko

def read_excel(file_path):
    '''
    读取设备清单表,将读取的表头和行数据组合成字典,字典组合成列表数据
    '''
    # 加载Excel文件并获取活动的sheet
    wb = openpyxl.load_workbook(file_path)
    sheet = wb.active

    data = []
    # 获取表头数据
    headers = [cell.value for cell in sheet[1]]
    # 遍历每一行数据,表头和行数据创建字典,
    for row in sheet.iter_rows(min_row=2, values_only=True):
        device_info = {}
        for header, value in zip(headers, row):
            device_info[header] = value
        # 将字典添加到数据列表中
        data.append(device_info)
    print('表格格式化数据,验证表格数据取数是否正常', data)
    return data


def ssh_connect(ip, username, password):
    '''创建 SSH 客户端对象,并设置自动添加主机密钥的策略'''
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(ip, username=username, password=password)
    return client

def execute_commands(client, commands):
    '''命令执行函数,遍历命令发送到交互式窗口,并收集输出'''
    outputs = []
    client = client.invoke_shell()
    for command in commands:
        client.send(command + "\n")  # 发送命令并换行
        time.sleep(1)  # 等待1秒,保证接收数据的完整性
        output = client.recv(65535).decode('utf-8')
        outputs.append(output)  # 命令执行结果添加到输出列表中
    client.close()
    return outputs

def main():
    '''输入设备清单表的位置,'''
    excel_file = "D:\TESTCORE\设备清单表.xlsx"
    devices = read_excel(excel_file)

    for device in devices:
        ip = device.get("设备登陆IP")
        username = device.get("设备登陆用户")
        password = device.get("设备登陆密码")
        commands = [
            device.get("设备输入命令1"),
            device.get("设备输入命令2"),
            device.get("设备输入命令3")
        ]

        try:
            client = ssh_connect(ip, username, password)
            outputs = execute_commands(client, commands)
            print(f"设备{ip}的命令输出结果:")
            for output in outputs:
                print(output)
        except Exception as e:
            print(f"连接错误 {ip}: {str(e)}")

if __name__ == "__main__":
    main()

3.4 脚本运行效果

运行正常的截图 image.png 修改设备清单表,设置密码为错误密码,运行截图如下: image.png 修改设备清单表,设置一个不存在的IP地址,运行截图如下: image.png 有时候知道错误原因比只知其然,而不知其所以然的成功更要紧。