You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Ansible中解析层级不同节点的Juniper设备XML库存

实现Juniper机箱XML库存的通配匹配与过滤

要实现你需要的功能,摆脱parse_xml过滤器的局限性,推荐结合Ansible的xml模块和XPath表达式来完成,这比直接用parse_xml更灵活,能轻松实现通配符式的层级匹配和条件过滤。

核心思路

  1. 用XPath匹配所有与chassis相关的各级节点(包括自身和所有子/孙模块)。
  2. 过滤掉serial-number属性值为BUILTIN的条目。

完整Playbook示例

---
- name: Parse Juniper chassis inventory and filter built-in modules
  hosts: junos_devices
  gather_facts: no
  tasks:
    # 1. 获取Juniper机箱硬件的XML格式输出
    - name: Fetch chassis hardware XML data
      junipernetworks.junos.junos_command:
        commands: "show chassis hardware | display xml"
      register: chassis_xml_raw

    # 2. 用XPath匹配所有chassis相关的各级节点
    # XPath逻辑:匹配所有节点名以chassis开头的节点,以及这些节点的所有子节点
    - name: Extract all chassis-related modules
      ansible.builtin.xml:
        xmlstring: "{{ chassis_xml_raw.stdout[0] }}"
        # 忽略XML命名空间(Juniper XML通常带命名空间,local-name()避免匹配失败)
        xpath: "//*[starts-with(local-name(), 'chassis') or ancestor::*[starts-with(local-name(), 'chassis')]]"
        content: attribute  # 提取节点的所有属性
      register: chassis_modules_raw

    # 3. 过滤掉serial-number为BUILTIN的条目
    - name: Filter out BUILTIN serial-number entries
      ansible.builtin.set_fact:
        filtered_modules: "{{ chassis_modules_raw.matches | rejectattr('serial-number', 'equalto', 'BUILTIN') | list }}"

    # 验证结果
    - name: Display filtered chassis modules
      ansible.builtin.debug:
        var: filtered_modules

关键细节说明

  • XPath表达式://*[starts-with(local-name(), 'chassis') or ancestor::*[starts-with(local-name(), 'chassis')]]

    • starts-with(local-name(), 'chassis'):匹配所有节点名以chassis开头的节点(比如chassis、chassis-module等)。
    • ancestor::*[starts-with(local-name(), 'chassis')]:匹配所有父/祖节点是chassis开头的子节点,覆盖各级子模块。
    • 用local-name()是因为Juniper的XML输出通常带有命名空间,直接用节点名会匹配失败。
  • 过滤逻辑:使用Ansible内置的rejectattr过滤器,直接剔除serial-number等于BUILTIN的条目,简洁高效。

替代方案(如果必须用parse_xml)

如果因为某些限制必须使用parse_xml过滤器,需要先将XML转换为字典,再通过递归遍历字典来匹配包含chassis的键并过滤:

- name: Convert XML to dict with parse_xml
  ansible.builtin.set_fact:
    chassis_dict: "{{ chassis_xml_raw.stdout[0] | parse_xml }}"

# 自定义递归查找逻辑(Jinja2实现)
- name: Recursively collect chassis-related entries
  ansible.builtin.set_fact:
    raw_modules: "{{ raw_modules | default([]) + ([item] if 'serial-number' in item else []) + (item.values() | select('is_dict') | map('recursive_collect') | flatten) }}"
  loop: "{{ chassis_dict.values() | flatten }}"

- name: Filter out BUILTIN entries
  ansible.builtin.set_fact:
    filtered_modules: "{{ raw_modules | rejectattr('serial-number', 'equalto', 'BUILTIN') | list }}"

这种方式需要额外处理递归逻辑,不如XPath方案简洁,仅作为兼容场景的备选。

内容的提问来源于stack exchange,提问作者ankost403

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 01:50:30