Netmiko 源码解析

1. 源码结构概览

Netmiko 的代码库主要分为以下核心模块:

netmiko/
├── base_connection.py    # 连接基类(核心逻辑)
├── cisco/                # Cisco 设备实现类
├── juniper/              # Juniper 设备实现类
├── hp_procurve/          # HP 设备实现类
├── ...                   # 其他厂商目录
├── ssh_dispatcher.py     # 设备类型与类的映射
├── utilities.py          # 辅助函数(如处理输出)
└── exceptions.py         # 自定义异常类

2. 核心类解析

BaseConnection 类(base_connection.py)
  • 作用:所有设备连接类的基类,定义了 SSH 连接管理、命令发送、模式切换等核心方法。
  • 关键方法
    class BaseConnection(object):
        def __init__(self, **kwargs): 
            # 初始化参数(host、username、password等)
            self.host = kwargs.get('host')
            self.establish_connection()  # 建立 SSH 连接
    
        def establish_connection(self):
            # 调用 Paramiko 的 SSHClient 创建连接
            self.remote_conn = paramiko.SSHClient()
            self.remote_conn.connect(**ssh_params)
    
        def send_command(self, command, **kwargs):
            # 发送命令,等待输出完成
            self._write_channel(command + '\n')
            output = self._read_channel()
            return output
    
        def _read_channel(self):
            # 读取 SSH 通道的输出(处理缓冲和超时)
            while not output.endswith(self.prompt):
                time.sleep(0.1)
                output += self.remote_conn.recv(65535).decode()
            return output
    
厂商子类(如 CiscoIosBase)
  • 作用:继承 BaseConnection,针对特定设备定制行为(如提示符、模式切换命令)。
    class CiscoIosBase(BaseConnection):
        def session_preparation(self):
            # 进入 enable 模式,设置终端长度
            self.enable()
            self.set_terminal_width()
    
        def enable(self, cmd='enable', pattern='password'):
            # 发送 enable 命令并处理密码输入
            self.write_channel(cmd + '\n')
            self.write_channel(self.secret + '\n')
    

3. 关键流程分析

连接初始化流程
  1. 设备类型映射

    • 用户指定 device_type(如 cisco_ios)。
    • ssh_dispatcher.py 中的 ConnectHandler 函数根据类型选择对应的厂商类。
    def ConnectHandler(**kwargs):
        device_type = kwargs['device_type']
        klass = ssh_dispatcher(device_type)  # 返回 CiscoIosBase 等类
        return klass(**kwargs)
    
  2. SSH 连接建立

    • 调用 Paramiko 库创建 SSH 会话,处理认证(密码或密钥)。
    • 设置会话参数(超时、终端类型)。
  3. 会话准备

    • 自动执行 session_preparation()(如进入 enable 模式、关闭分页)。

命令执行流程(以 send_command 为例)
  1. 发送命令

    def send_command(self, command, **kwargs):
        self._write_channel(command + '\n')  # 向通道写入命令
    
  2. 读取输出

    • 通过 _read_channel() 循环读取 SSH 通道数据,直到匹配设备提示符。
    • 使用 delay_factormax_loops 控制等待时间,防止超时。
  3. 输出处理

    • 清除命令回显(如去除输入的 show version 字符串)。
    • 可选使用 TextFSM 或 Genie 进行结构化解析。

配置模式处理(send_config_set
  1. 进入配置模式
    • 自动发送 configure terminal(或其他厂商等效命令)。
  2. 逐行发送配置
    for cmd in config_commands:
        self.send_command(cmd)
    
  3. 退出配置模式
    • 发送 exitend 命令,返回特权模式。

4. 关键设计思想

多态与继承
  • 所有厂商类继承自 BaseConnection,重写特定方法(如 enable())以适配设备差异。
  • 例如,Juniper 设备的配置模式使用 configure private,而 Cisco 使用 configure terminal
    class JuniperJunosBase(BaseConnection):
        def config_mode(self, config_command='configure private'):
            self.write_channel(config_command + '\n')
    
SSH 通道管理
  • 使用 Paramiko 的 SSHClient 创建通道,通过 _read_channel()_write_channel() 实现读写分离。
  • 缓冲区和超时机制确保输出完整性。
异常处理
  • 自定义异常类(如 NetmikoTimeoutException)在关键节点抛出:
    def _read_channel(self):
        if time.time() > end_time:
            raise NetmikoTimeoutException("读取超时!")
    

5. 调试与扩展

调试技巧
  • 启用日志
    import logging
    logging.basicConfig(level=logging.DEBUG)
    
  • 修改源码:在关键方法中添加 print 语句跟踪执行流程。
扩展新设备支持
  1. 创建子类
    class CustomDevice(BaseConnection):
        def session_preparation(self):
            self.enable()
            self.set_terminal_width()
    
  2. 注册设备类型
    def ssh_dispatcher(device_type):
        if device_type == 'custom_device':
            return CustomDevice
    

6. 源码分析工具建议

  • IDE 调试:使用 PyCharm 或 VS Code 设置断点跟踪执行。
  • 代码跳转:结合 ctagsGo to Definition 快速导航代码。
  • UML 生成:生成类图(如 pyreverse)直观查看继承关系。

通过源码分析,你可以更灵活地解决复杂问题(如适配非标准设备)、优化性能(调整超时参数),或贡献代码到开源社区。建议结合官方文档和实际调试逐步深入。

你可能感兴趣的:(NetDevOps,智联空间,自动化,网络自动化,网络自动化运维,NetDevOps)