4. NETCONF协议与Comware实践

NETCONF(Network Configuration Protocol,网络配置协议)由IETF在RFC 6241中定义,它把网络设备的配置管理抽象为“配置数据库 + RPC操作”的模型。与CLI逐条敲命令、SNMP以MIB变量读写为主的思路不同,NETCONF用XML编码数据、用RPC封装操作、用YANG描述模型,使配置下发具备结构化、可校验、可回滚的特性。在Comware设备上,NETCONF通常运行在SSH之上(端口830),由设备充当NETCONF Server,运维脚本或平台充当Client。

理解NETCONF,关键是抓住四个概念:能力集(Capabilities)、会话(Session)、数据存储(Datastore)和RPC操作。能力集在会话建立时通过<hello>消息交换,双方各自声明支持哪些能力;数据存储则区分running(运行配置)、candidate(候选配置,Comware支持时可用)、startup(启动配置)。RPC操作包括<get>、<get-config>、<edit-config>、<copy-config>、<lock>/<unlock>、<commit>等,分别对应读取、下发、复制、加锁与提交。

NETCONF 会话与 RPC 交互时序(Comware 设备) ncclient(Client) Comware(NETCONF Server) ① SSH 连接建立(TCP 830) ② <hello> 能力集声明(base:1.1, candidate, writable-running…) ③ <hello> 响应(Server 能力集) ④ <get-config> 读取 running 配置 ⑤ <rpc-reply> 返回 XML 配置数据 ⑥ <lock> 锁定 candidate/running ⑦ <edit-config> 下发配置(merge/replace) ⑧ <ok/> 或 <rpc-error> 结果 ⑨ <commit> 提交 / <unlock> 解锁 ⑩ 提交确认,配置生效

能力集协商:会话能否继续的前提

NETCONF会话建立后,双方立即互发<hello>。Client的hello中<capabilities>列出自己支持的能力,Server的hello则列出设备支持的能力。Comware设备典型能力包括:urn:ietf:params:netconf:base:1.1、urn:ietf:params:netconf:capability:candidate:1.0、urn:ietf:params:netconf:capability:writable-running:1.0、urn:ietf:params:netconf:capability:rollback-on-error:1.0,以及厂商私有能力如urn:h3c:params:netconf:capability:h3c-1.0。Client必须根据Server返回的能力集决定后续操作:若Server不支持candidate,就不能使用<commit>,只能直接编辑running。

ncclient在connect()时自动完成hello交换,并把Server能力集保存在manager.server_capabilities中。实际脚本中应先检查关键能力,再决定操作路径,例如:

from ncclient import manager

with manager.connect(
        host="192.0.2.10", port=830,
        username="netops", password="NetOps@123",
        hostkey_verify=False,
        device_params={"name": "h3c"},
        timeout=30) as m:
    caps = m.server_capabilities
    print("base:1.1" in str(caps))
    print("candidate" in str(caps))

这里device_params={"name": "h3c"}用于加载H3C厂商适配,使ncclient能正确处理Comware的命名空间与RPC格式。若省略该参数,部分操作可能因命名空间不匹配而返回unknown-element错误。

读取配置:get 与 get-config 的差异

<get>用于获取设备运行状态与配置的混合数据,可带<filter>;<get-config>只读取指定数据存储的配置,必须指定<source>。在Comware上读取接口配置的示例:

filter = """
<filter xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"/>
</filter>
"""
reply = m.get_config(source="running", filter=filter)
print(reply.xml)

返回的<rpc-reply>中<data>节点即为结构化配置。判断读取是否成功,主要看两点:一是reply.ok为True且无<rpc-error>;二是<data>中确实包含目标节点。若返回<data/>为空,通常是filter命名空间或路径写错,而非设备无配置。

下发配置:edit-config 与错误处理

下发配置使用<edit-config>,其operation属性可取merge(默认,合并)、replace(替换)、create、delete、remove。Comware上修改接口描述与开启接口的示例:

config = """
<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
  <interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces">
    <interface>
      <name>GigabitEthernet1/0/1</name>
      <description>Uplink-to-Core</description>
      <enabled>true</enabled>
    </interface>
  </interfaces>
</config>
"""
m.edit_config(target="running", config=config, default_operation="merge")

若设备支持candidate,更稳妥的做法是:lock(candidate) → edit_config(target="candidate") → validate → commit → unlock。这样在提交前可校验,出错时用discard-changes回滚,避免半成品配置直接生效。Comware对candidate的支持随版本与License不同,脚本应先探测能力集再选择路径。

注意:<edit-config>返回<ok/>只代表RPC被接受,不代表配置一定生效。应再用<get-config>回读目标节点,或通过CLI display current-configuration interface交叉验证。

常见错误与排查

NETCONF操作失败时,<rpc-error>会给出error-type、error-tag、error-message。常见情形:operation-not-supported表示设备不支持该操作(如无candidate却调用commit);data-missing表示引用的节点不存在;lock-denied表示配置已被其他会话锁定;invalid-value表示参数取值非法。排查顺序建议为:先看能力集是否匹配,再看filter/命名空间是否正确,最后看目标节点路径与取值是否符合YANG模型约束。

实践建议:把“能力探测—读取—加锁—编辑—提交—回读”封装为可复用函数,并在每次下发前记录server_capabilities与操作前后配置快照,便于审计与回滚。

综合来看,NETCONF在Comware上的落地并不复杂,难点在于能力集协商的兼容性判断、XML命名空间与YANG路径的准确性,以及提交与回滚的边界控制。掌握这三者,就能用ncclient把配置读取与下发做成稳定、可审计的自动化流程。