clay584.parse_genie
解析精灵
注意!!! - 如果您遇到命令解析失败的问题,可能是 Cisco 维护的解析库中存在错误。对于这些问题,您可以在这里提交问题。
网络解析精灵过滤器将所有 Cisco 网络操作系统的非结构化网络 CLI 命令输出转换为结构化数据。虽然与其他可用的网络 CLI 解析器(如 parse_cli, parse_cli_textfsm)相似,但此解析器是由 Cisco 开发的成熟且强大的库 Genie(及其底层框架 pyATS)提供支持。它提供了超过1200个解析器,可以将配置和 CLI 输出转换为结构化数据,这些数据是规范化的,并符合标准的、与操作系统无关的数据模型。
Genie 库也可以作为引擎,使用比传统解析需要更少的代码解析表格和非表格的自由格式文本。因此,它可以用于解析任何厂商的输出,而不仅限于 Cisco 设备的输出。但是,这将涉及编写自定义解析器。本版本不包含使用自定义解析器的功能。支持的解析器为用户在其 Ansible 控制机上安装的 Genie 版本中包含的解析器。
支持的操作系统和命令列表,以及数据模式定义(描述任何给定命令将返回哪些字段和数据类型),可通过以下链接从 Cisco 获取。
https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers
前提条件
此插件需要以下内容:
- Python 3.4+
- pyATS 和 Genie 包
- Ansible 2.7+(只要满足其他要求,应该可以在更旧的版本上工作)
安装
请按照以下说明操作,确保过滤插件可以在您的剧本中正常工作:
- 创建一个目录用于您的剧本并进入该目录。
mkdir network_ops && cd network_ops
- 创建一个虚拟环境。
python3 -m venv .venv
- 激活虚拟环境。
source .venv/bin/activate
- 安装 Ansible。
pip install ansible
- 安装 Genie 和 pyATS。
pip install genie
- 从 Ansible Galaxy 安装 parse_genie 角色。
ansible-galaxy install clay584.parse_genie
Ansible 到 Genie 操作系统映射
以下是 Ansible 的 ansible_network_os
到 Genie 的 os
的映射:
Ansible 网络操作系统 | Genie 操作系统 |
---|---|
ios | ios, iosxe |
nxos | nxos |
iosxr | iosxr |
junos | junos |
如果您使用的是 IOS 或 IOS-XE,可能会存在歧义,因为 Ansible 将 IOS 和 IOS-XE 视为相同,因此 ansible_network_os = ios
,但 Genie 需要明确知道它是 IOS 还是 IOS-XE,以便正确解析 CLI 输出。如果您将 ansible_network_os
传递给此过滤插件,并且其值等于 ios
,parse_genie 将首先尝试使用 os=ios
进行解析,如果失败,则将尝试使用 os=iosxe
进行解析。
因此,在创建剧本时请记住这一点。最好是将实际的操作系统传递给 parse_genie。您可以通过维持另一个库存变量或主机变量来指定每个网络设备的 Genie 操作系统,然后使用该变量作为 parse_genie 的操作系统。
使用方法
在尝试在剧本中使用 parse_genie 之前,请确保先读取 parse_genie 角色。
...省略...
tasks:
- name: 读取 parse_genie 角色
include_role:
name: clay584.parse_genie
...省略...
简短示例
要将网络设备 CLI 命令的输出转换为结构化数据,如下例所示使用 parse_genie
过滤器(请勿使用简化的 CLI 命令)。
将来自 Cisco IOS-XE 设备的 show version
命令的 CLI 输出转换为结构化数据:
{{ cli_output | parse_genie(command='show version', os='iosxe') }}
为了更深层次的抽象,您可能还想向 parse_genie
添加 platform
。
{{ cli_output | parse_genie(command='show version', os='iosxe', platform='asr1k') }}
上述示例将产生以下结果:
{
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "virtual hard disk"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "WebUI ODM Files"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "production image",
"last_reload_reason": "Reload Command",
"license_level": "ax",
"license_type": "Default. No valid license found.",
"main_mem": "1126522",
"mem_size": {
"non-volatile configuration": "32768",
"physical": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutes",
"uptime_this_cp": "3 minutes",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
完整示例 #1
剧本:
---
- hosts: localhost
connection: local
vars:
show_version_output: |
Cisco IOS XE 软件,版本 16.05.01b
Cisco IOS 软件 [Everest], 虚拟 XE 软件 (X86_64_LINUX_IOSD-UNIVERSALK9-M), 版本 16.5.1b, 发行软件 (fc1)
技术支持: http://www.cisco.com/techsupport
版权所有 (c) 1986-2017 由 Cisco 系统公司。
编译于 2017 年 4 月 11 日星期二 16:41,编写者 mcpre
Cisco IOS-XE 软件,版权所有 (c) 2005-2017 由 Cisco 系统公司。
版权所有。 Cisco IOS-XE 软件的某些组件根据 GNU 通用公共许可证("GPL") 版本 2.0 获得许可。
根据 GPL 版本 2.0 授权的代码是免版权费的软件,完全不提供任何保证。您可以根据 GPL 版本 2.0 的条款重新分发和/或修改此代码。
有关更多详细信息,请参阅与 IOS-XE 软件一起提供的文档或“许可证通知”文件,或提供在 IOS-XE 软件随附的传单中的适用 URL。
ROM: IOS-XE ROMMON
host-172-16-1-96 正在运行 2 分钟
此控制处理器的运行时间为 3 分钟
系统返回 ROM 由于重新加载
系统映像文件为 "bootflash:packages.conf"
上次重新加载原因: 重新加载命令
本产品包含加密功能,受美国及当地国家进口、出口、转移和使用法律的制约。交付 Cisco 加密产品不代表第三方有权导入、导出、分发或使用加密。
进口商、出口商、分销商和用户负责遵守美国和当地国家法律。使用本产品即表示您同意遵守适用的法律法规。如果您无法遵守美国和当地法律,请立即退还此产品。
美国法律概述适用于 Cisco 加密产品,您可以在以下网址查找到:
http://www.cisco.com/wwl/export/crypto/tool/stqrg.html
如需进一步帮助,请通过电子邮件联系 [email protected]。
许可证级别: ax
许可证类型: 默认。未找到有效许可证。
下次重新加载许可证级别: ax
cisco CSR1000V (VXE) 处理器 (修订版 VXE) 拥有 1126522K/3075K 字节内存。
处理器板 ID 9TKUWGKX5MO
2 个千兆以太网接口
32768K 字节非易失性配置内存。
3018840K 字节物理内存。
7774207K 字节虚拟硬盘在 bootflash:。
0K 字节 WebUI ODM 文件在 webui:。
配置寄存器为 0x2102
tasks:
- name: 读取 parse_genie 角色
include_role:
name: clay584.parse_genie
- name: 调试 Genie 过滤器
debug:
msg: "{{ show_version_output | parse_genie(command='show version', os='iosxe') }}"
delegate_to: localhost
输出:
$ ansible-playbook -i inventory debug.yml
PLAY [localhost] *************************************************************************
TASK [收集事实] *******************************************************************
ok: [localhost]
TASK [读取 parse_genie 角色] **********************************************************
TASK [调试 Genie 过滤器] ****************************************************************
ok: [localhost -> localhost] => {
"msg": {
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "virtual hard disk"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "WebUI ODM Files"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "production image",
"last_reload_reason": "Reload Command",
"license_level": "ax",
"license_type": "Default. No valid license found.",
"main_mem": "1126522",
"mem_size": {
"non-volatile configuration": "32768",
"physical": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutes",
"uptime_this_cp": "3 minutes",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
}
完整示例 #2
剧本:
---
- hosts: csr1000v
gather_facts: False
tasks:
- name: 读取 parse_genie 角色
include_role:
name: clay584.parse_genie
- name: 从设备获取数据
ios_command:
commands: show arp vrf Mgmt-intf
register: arp_output
- name: 打印结构化数据
debug:
msg: "{{ arp_output['stdout'][0] | parse_genie(command='show arp vrf Mgmt-intf', os='iosxe') }}"
delegate_to: localhost
输出:
$ ansible-playbook -i inventory playbook.yml
PLAY [csr1000v] **************************************************************************
TASK [读取 parse_genie 角色] **********************************************************
TASK [从设备获取数据] **************************************************************
ok: [csr1000v]
TASK [打印结构化数据] *************************************************************
ok: [csr1000v -> localhost] => {
"msg": {
"interfaces": {
"GigabitEthernet1": {
"ipv4": {
"neighbors": {
"172.16.1.111": {
"age": "0",
"ip": "172.16.1.111",
"link_layer_address": "5e00.4004.0000",
"origin": "dynamic",
"protocol": "Internet",
"type": "ARPA"
},
"172.16.1.114": {
"age": "-",
"ip": "172.16.1.114",
"link_layer_address": "5e00.4001.0000",
"origin": "static",
"protocol": "Internet",
"type": "ARPA"
}
}
}
}
}
}
}
通用表格解析
Cisco Genie 支持 1200 个命令,并且数量还在增加,但对于没有由 Cisco 构建的解析器的显示命令,可以使用通用表格解析功能。有关 Genie 表格解析功能的更多信息,请参见他们的oper_fill_tabular文档。
表格解析的工作原理
为了当有解析器时解析命令输出,只需提供 command
、command output
和 os
。但是,如果没有构建解析器,您必须指定一些额外的信息,以帮助解析器确定如何解析命令输出。这些额外的数据有两个部分:
- 表头 - 作为命令输出的一部分显示的列标题。
- 索引 - 解析器将返回的字典项的关键字。
考虑以下示例:
- 命令:
show ip sla summary
- 命令输出:
IPSLAs 最新操作摘要
代码: * 活动, ^ 非活动, ~ 待定
所有统计数据均以毫秒为单位。带有 u 的统计数据以微秒为单位
ID 类型 目标地址 统计数据 返回 上次执行
代码 执行
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK 20 秒前
*2 icmp-echo 10.0.0.2 RTT=1 OK 3 秒前
- 表头 -
ID
,类型
,目标地址
,统计数据
,返回代码
,上次执行
。 - 索引 - 我们希望使用
ID
列作为从解析器获取回来的数据的索引。 - 解析器输出:
{'*1': {'目标地址 ': '10.0.0.2',
'ID ': '*1',
'上次执行': '20 秒前',
'返回代码': 'OK',
'统计 ': 'RTT=900u',
'类型 ': 'udp-jitter'},
'*2': {'目标地址 ': '10.0.0.2',
'ID ': '*2',
'上次执行': '3 秒前',
'返回代码': 'OK',
'统计 ': 'RTT=1',
'类型 ': 'icmp-echo'}}
准备使用表格解析器
为了使用此表格解析器,我们必须首先为给定操作系统上的给定命令构建 headers
和 index
,格式可以被 Ansible 剧本读取,并随后传递给 parse_genie 过滤插件。
为此,您必须在剧本中创建一个变量文件,格式如下。它按照操作系统,然后是命令组织。在每个命令下,定义了表头和索引。您可以为每个网络操作系统定义任意数量的命令,只要在此数据结构中即可。
parse_genie:
ios:
"show ip sla summary":
headers:
- - ID
- 类型
- 目标地址
- 统计
- 返回
- 上次
- - ''
- ''
- ''
- ''
- 代码
- 执行
index:
- 0
iosxe:
"show ip sla summary":
headers:
- - ID
- 类型
- 目标地址
- 统计
- 返回
- 上次
- - ''
- ''
- ''
- ''
- 代码
- 执行
index:
- 1
上述 yaml 格式的 Python 等效代码是:
python_dict = {
"parse_genie": {
"ios": {
"show ip sla summary": {
"headers": [
[
"ID",
"类型",
"目标地址",
"统计",
"返回",
"上次"
],
[
"",
"",
"",
"",
"代码",
"执行"
]
],
"index": [
0
]
}
},
"iosxe": {
"show ip sla summary": {
"headers": [
[
"ID",
"类型",
"目标地址",
"统计",
"返回",
"上次"
],
[
"",
"",
"",
"",
"代码",
"执行"
]
],
"index": [
1
]
}
}
}
}
在剧本中调用表格解析器
现在我们已经定义了通用表格命令及其头和索引,我们可以从剧本中实际调用它。
首先,我们读取包含表格命令解析元数据的变量文件。
- name: 包含含有通用命令元数据的变量文件
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
接下来,我们将命令输出传递给 parse_genie
,但稍多几个额外参数。
- name: 解析通用表格命令输出
debug:
msg: "{{ command_output | parse_genie(command='show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
解析后的输出如下所示:
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"目标地址 ": "10.0.0.2",
"ID ": "*1",
"上次执行": "20 秒前",
"返回代码": "OK",
"统计 ": "RTT=900u",
"类型 ": "udp-jitter"
},
"*2": {
"目标地址 ": "10.0.0.2",
"ID ": "*2",
"上次执行": "3 秒前",
"返回代码": "OK",
"统计 ": "RTT=1",
"类型 ": "icmp-echo"
}
}
}
完整示例 #1
剧本:
---
- hosts: localhost
connection: local
vars:
out_ios_sla: |
IPSLAs 最新操作摘要
代码: * 活动, ^ 非活动, ~ 待定
所有统计数据均以毫秒为单位。带有 u 的统计数据以微秒为单位
ID 类型 目标地址 统计数据 返回 上次执行
代码 执行
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK 20 秒前
*2 icmp-echo 10.0.0.2 RTT=1 OK 3 秒前
tasks:
- name: 包含解析精灵角色
include_role:
name: clay584.parse_genie
- name: 包含含有通用表格命令元数据的变量文件
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
- name: 测试通用表格数据的 Genie 过滤器
debug:
msg: "{{ out_ios_sla | parse_genie(command='test show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
parse_genie_generic_commands.yml
内容:
---
parse_genie:
ios:
"test show ip sla summary":
headers:
- - ID
- 类型
- 目标地址
- 统计
- 返回
- 上次
- - ''
- ''
- ''
- ''
- 代码
- 执行
index:
- 0
iosxe:
"test show ip sla summary":
headers:
- - ID
- 类型
- 目标地址
- 统计
- 返回
- 上次
- - ''
- ''
- ''
- ''
- 代码
- 执行
index:
- 1
剧本输出:
PLAY [localhost] ******************************************************************************************************************************************************************************************************************************************************************
TASK [收集事实] ************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [包含解析精灵角色] ***************************************************************************************************************************************************************************************************************************************************
TASK [包含变量] ***************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [测试通用表格数据的 Genie 过滤器] *********************************************************************************************************************************************************************************************************************************
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"目标地址 ": "10.0.0.2",
"ID ": "*1",
"上次执行": "20 秒前",
"返回代码": "OK",
"统计 ": "RTT=900u",
"类型 ": "udp-jitter"
},
"*2": {
"目标地址 ": "10.0.0.2",
"ID ": "*2",
"上次执行": "3 秒前",
"返回代码": "OK",
"统计 ": "RTT=1",
"类型 ": "icmp-echo"
}
}
}
PLAY RECAP ************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
开发
设置您的开发环境:
- 克隆该仓库并进入。
git clone https://github.com/clay584/parse_genie.git && cd parse_genie
- 创建一个虚拟环境。
python3 -m venv .venv
- 激活虚拟环境。
source .venv/bin/activate
- 安装 Ansible。
pip install ansible
- 安装 Genie 和 pyATS。
pip install genie
- 安装 yamllint。
pip install yamllint
测试
运行这些命令进行本地测试:
- 检查所有 YAML 文件的语法。
yamllint -c yamllint_config.yml *
- 运行测试剧本。
ansible-playbook tests/test.yml --connection=local -i tests/inventory
推送
Ansible Galaxy 在标签上工作。
git commit -m"whatever'
git tag -a X.X.X
- 其中 X.X.X 是语义版本号。git push origin master
git push X.X.X