在 Ansible作指南中使用 Python 中的 Junos 快照管理员 (JSNAPy)
将 JSNAPy 测试作为 Ansible作指南的一部分来执行,以捕获和审核 Junos 设备的运行时环境快照。
Python 中的 Junos® 快照管理员 (JSNAPy) 允许您捕获和审核 Junos 设备的运行时环境快照。您可以捕获并验证设备的配置和作状态,并验证对设备所做的更改。瞻博网络提供了一个 Ansible 模块,作为 Ansible 指南的一部分,您可以使用该模块对 Junos 设备执行 JSNAPy 测试。 表 1 概述了可用的模块。
内容集 |
模块名称 |
---|---|
您必须在 Ansible 控制节点上的 Python 中安装 Junos Snapshot Administrator,才能使用该 juniper.device.jsnapy
模块。有关安装说明以及有关创建 JSNAPy 配置和测试文件的信息,请参阅 Python 文档中的 Junos Snapshot Administrator。
以下各节讨论如何在 Ansible作指南中使用该 juniper.device.jsnapy
模块。
模块概述
该 juniper.device.jsnapy
模块使您能够从 Ansible作指南中执行 JSNAPy 功能,包括:
-
捕获并保存运行时环境快照
-
比较两个快照
-
捕获快照并立即对其进行评估
该模块需要指定 action
参数和 或 config_file
参数 test_files
。该 action
参数指定要执行的 JSNAPy作。 表 2 概述了有效 action
值和等效的 JSNAPy 命令。
action 值 |
描述 |
等效的 JSNAPy 命令 |
---|---|---|
|
根据给定的测试用例比较两个现有快照,或者如果未提供测试用例,则逐个节点比较快照。 |
|
|
在给定设备上进行更改后,为测试文件中指定的命令或 RPC 拍摄快照。 |
|
|
在对给定设备进行更改之前,请为测试文件中指定的命令或 RPC 拍摄快照。 |
|
|
拍摄测试文件中指定的命令或 RPC 的快照,并立即根据测试用例中的预定义标准评估快照。 |
|
在命令行上执行 JSNAPy 时,JSNAPy 将对配置文件 hosts
部分中指定的主机执行请求的作。相反,Ansible 模块会在 Ansible作指南中指定的主机上执行请求的作。因此,该模块可以引用配置文件(忽略该 hosts
部分),也可以直接引用一个或多个测试文件。
因此,除了 action
参数之外,模块 juniper.device.jsnapy
还需要 config_file
参数或 test_files
参数来指定用于给定作的 JSNAPy 配置文件或 JSNAPy 测试文件。 表 3 概述了 config_file
和 test_files
参数。
模块参数 |
价值 |
其他信息 |
---|---|---|
|
JSNAPy 配置文件的绝对或相对文件路径。 |
如果路径是相对路径,则模块将按指示的顺序在以下位置检查配置文件:
如果配置文件使用相对文件路径引用测试文件,则模块将首先检查 playbook 目录中的测试文件,然后检查缺省 |
|
JSNAPy 测试文件的绝对或相对文件路径。这可以是单个文件路径,也可以是文件路径列表。 |
对于每个指定相对路径的测试文件,模块将在以下位置按指示的顺序检查该文件:
|
config_file
和 test_files
参数可以采用绝对或相对文件路径。使用相对文件路径时,可以选择包含 dir
module 参数以指定文件所在的目录。config_file
如果 或 test_files
参数使用相对文件路径,则模块会首先检查 Ansible playbook 目录中的文件,即使该dir
参数存在也是如此。如果该文件在 playbook 目录中不存在,则模块在dir
参数目录中检查(如果指定了该文件),或者在 dir
/etc/jsnapy/testfiles 目录中检查(如果省略了参数)。如果找不到文件,playbook 将生成错误消息。
请务必注意,当您包含参数 dir
时,模块仅检查该位置的指定 config_file
或 test_files
参数。因此,当您指定配置文件时,该模块不会检查您在配置文件中指定的测试文件的 dir
目录。如果配置文件引用测试文件的相对路径,则模块仅在 playbook 目录和默认 testfiles
目录中检查测试文件。
假设您有以下 JSNAPy 配置文件 jsnapy_config_base_tests.yaml,它位于 ~/jsnapy/testfiles 目录中,并引用了多个 JSNAPy 测试文件:
user@ansible-cn:~/ansible$ cat ~/jsnapy/testfiles/jsnapy_config_base_tests.yaml tests: - system_util_baseline.yaml - verify_ldp_neighbors.yaml - verify_ospf_neighbors.yaml - verify_bgp_neighbors.yaml - test_interface_operstate.yaml
以下示例 playbook 对 jsnapy_config_base_tests.yaml 配置文件中的每个测试文件执行snap_pre
作。如果配置文件在 playbook 目录中不存在,则模块会检查该目录中的dir
文件,在本例中为 ~/jsnapy/testfiles。配置文件使用测试文件的相对路径。因此,该模块首先检查 playbook 目录中的测试文件,然后检查默认 testfiles 目录中的测试文件。
--- - name: Junos Snapshot Administrator tests hosts: dc1a connection: local gather_facts: no tasks: - name: Take a pre-maintenance snapshot juniper.device.jsnapy: action: "snap_pre" dir: "~/jsnapy/testfiles" config_file: "jsnapy_config_base_tests.yaml"
或者,模块 jsnapy
可以使用参数 test_files
来指定要使用的单个测试文件。以下 playbook 执行的测试与上一个 playbook 示例中的测试相同。在这种情况下,模块首先检查 playbook 目录中的测试文件,然后检查目录中的 dir
测试文件。
--- - name: Junos Snapshot Administrator tests hosts: dc1a connection: local gather_facts: no tasks: - name: Take a pre-maintenance snapshot juniper.device.jsnapy: action: "snap_pre" dir: "~/jsnapy/testfiles" test_files: - system_util_baseline.yaml - verify_ldp_neighbors.yaml - verify_ospf_neighbors.yaml - verify_bgp_neighbors.yaml - test_interface_operstate.yaml
从 Python 1.3.0 版的 Junos Snapshot Administrator 开始,配置和测试文件的默认位置为 ~/jsnapy/testfiles。但是,虚拟环境中或早期版本中的默认位置是 /etc/jsnapy/testfiles。
该模块会在 Ansible作指南中指定的主机上执行请求的作,即使该模块引用的配置文件包含某个 hosts
区段。如果模块遇到错误并且无法执行 JSNAPy 测试,则报告失败。如果一个或多个 JSNAPy 测试失败, 它不会报告失败 。要检查 JSNAPy 测试结果,请注册模块的响应,并使用该 ansible.builtin.assert
模块验证响应中的预期结果。
默认情况下,Python 中的 Junos 快照管理员会将有关其作的信息记录到 /var/log/jsnapy/jsnapy.log 文件中。该 juniper.device.jsnapy
模块可以选择包含参数 logfile
,该参数指定 Ansible 控制节点上可写文件的路径,用于记录特定任务的信息。Ansible 的详细级别和调试选项决定了文件中记录的信息级别。默认情况下,仅记录严重性级别为 WARNING 或更高级别的消息。要记录等于或高于严重性级别 INFO 或严重性级别 DEBUG 的消息,请分别使用 -v
或 -vv
命令行选项执行 playbook。
在 Ansible作指南中执行 JSNAPy 测试时,可以保存或汇总失败的 JSNAPy 测试的信息。有关更多信息,请参阅 查看失败的 JSNAPy 测试。
拍摄和比较快照
JSNAPy 允许您在更改前后捕获 Junos 设备的运行时环境快照,然后比较这些快照以验证预期的更改或识别意外问题。该 juniper.device.jsnapy
模块使您能够拍摄和比较 JSNAPy 快照,作为 Ansible作指南的一部分。该模块使用预先确定的文件名将每个主机的每个快照保存在缺省 JSNAPy 快照目录中的单独文件中。有关输出文件的更多信息,请参阅 了解 jsnapy 模块输出。
若要在进行更改之前拍摄一个或多个设备的基线快照,请将模块的 action
参数设置为 snap_pre
,并指定一个配置文件或一个或多个测试文件。
以下作指南保存 Ansible 清单组中每台设备的 PRE 快照。该任务引用 ~/jsnapy/testfiles 目录中的 jsnapy_config_base_tests.yaml 配置文件,并将消息记录到 playbook 目录中的 jsnapy_tests.log 文件。
--- - name: Junos Snapshot Administrator tests hosts: dc1 connection: local gather_facts: no tasks: - name: Take a pre-maintenance snapshot juniper.device.jsnapy: action: "snap_pre" dir: "~/jsnapy/testfiles" config_file: "jsnapy_config_base_tests.yaml" logfile: "jsnapy_tests.log"
要在执行更改后拍摄一个或多个设备的快照,请将模块的 action
参数设置为 snap_post
,并指定一个配置文件或一个或多个测试文件。
以下作指南保存 Ansible 清单组中每台设备的开机自检快照。该任务引用 ~/jsnapy/testfiles 目录中的相同 jsnapy_config_base_tests.yaml 配置文件,并将消息记录到 playbook 目录中的 jsnapy_tests.log 文件。
--- - name: Junos Snapshot Administrator tests hosts: dc1 connection: local gather_facts: no tasks: - name: Take a post-maintenance snapshot juniper.device.jsnapy: action: "snap_post" dir: "~/jsnapy/testfiles" config_file: "jsnapy_config_base_tests.yaml" logfile: "jsnapy_tests.log"
jsnapy
当模块执行snap_pre
作或作snap_post
时,它会使用自动生成的文件名将每个主机的每个快照保存在单独的文件中,这些文件名分别包含“PRE”或“POST”标记。要比较PRE
和POST
快照以快速验证更新或识别更改可能导致的任何问题,请将action
模块的参数设置为 check
,并指定用于拍摄快照的相同配置文件或测试文件。
当模块执行 check
作时,JSNAPy 会比较每个设备上每个测试的 PRE 和 POST 快照,并根据测试文件部分中 tests:
定义的标准对其进行评估。如果测试文件未定义任何测试用例,则 JSNAPy 将逐个节点比较快照。要检查测试结果,请注册模块的响应,并使用该 ansible.builtin.assert
模块验证响应中的预期结果。
以下指南比较了为之前执行 snap_pre
的快照和 snap_post
在 Ansible 清单组中的每台设备上执行的作。使用配置文件中引用的测试文件中的标准对结果进行评估。playbook 将模块的响应注册为“test_result
”,并使用该 ansible.builtin.assert
模块验证是否在给定设备上通过了所有测试。
--- - name: Junos Snapshot Administrator tests hosts: dc1 connection: local gather_facts: no tasks: - name: Compare PRE and POST snapshots juniper.device.jsnapy: action: "check" dir: "~/jsnapy/testfiles" config_file: "jsnapy_config_base_tests.yaml" logfile: "jsnapy_tests.log" register: test_result - name: Verify JSNAPy tests passed ansible.builtin.assert: that: - "test_result.passPercentage == 100"
运行作指南时,断言会快速确定哪些设备未通过测试。
user@host:~$ ansible-playbook jsnapy-baseline-check.yaml PLAY [Junos Snapshot Administrator tests] ************************************* TASK [Compare PRE and POST snapshots] ***************************************** ok: [dc1a.example.net] ok: [dc1b.example.net] TASK [Verify JSNAPy tests passed] ********************************************* ok: [dc1b.example.net] => { "changed": false, "msg": "All assertions passed" } fatal: [dc1a.example.net]: FAILED! => { "assertion": "test_result.passPercentage == 100", "changed": false, "evaluated_to": false, "msg": "Assertion failed" } to retry, use: --limit @/home/user/jsnapy-baseline-check.retry PLAY RECAP ******************************************************************** dc1b.example.net : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 dc1a.example.net : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
执行快照检查作
JSNAPy 使您能够为 JSNAPy 测试文件中指定的命令或 RPC 拍摄快照,并立即根据测试用例中的预定义标准评估快照。该 juniper.device.jsnapy
模块使您能够执行 JSNAPy 快照检查作,作为 Ansible作手册的一部分。
要拍摄快照并立即根据测试文件部分中预定义的一组条件 tests:
对其进行评估,请将 action
模块的参数设置为 snapcheck
,并指定一个配置文件或一个或多个测试文件。要检查测试结果,请注册模块的响应,并使用该 ansible.builtin.assert
模块验证响应中的预期结果。
例如,对于 Ansible 清单组中的每个设备,以下作指南会为测试文件中的每个命令或 RPC 保存单独的快照,注册模块的响应,并使用该 ansible.builtin.assert
模块验证测试文件中定义的所有测试是否在该设备上传递。
--- - name: Junos Snapshot Administrator tests hosts: dc1 connection: local gather_facts: no tasks: - name: Take a snapshot and immediately evaluate it juniper.device.jsnapy: action: "snapcheck" dir: "~/jsnapy/testfiles/" test_files: - "test_interface_status.yaml" - "test_bgp_neighbor.yaml" logfile: "jsnapy_tests.log" register: test_result - name: Verify JSNAPy tests passed ansible.builtin.assert: that: - "test_result.passPercentage == 100"
了解 jsnapy 模块输出
juniper.device.jsnapy
当模块执行、 snap_pre
snap_post
或 snapcheck
作时,它会自动将快照保存在 JSNAPy 快照目录中。该模块使用缺省的 JSNAPy 目录,除非您修改 JSNAPy 配置文件 (jsnapy.cfg) 以指定其他位置。该模块会为 Ansible 清单组中在每台设备上执行的每个命令或 RPC 创建一个单独的文件。表 4 概述了参数的每个值action
的快照文件的文件名。
从 Python 1.3.0 版的 Junos Snapshot Administrator 开始,JSNAPy 测试文件和快照的默认目录分别为 ~/jsnapy/testfiles 和 ~/jsnapy/snapshots。但是,虚拟环境中或早期版本的默认目录是 /etc/jsnapy/testfiles 和 /etc/jsnapy/snapshots。
|
输出文件 |
---|---|
|
hostname_PRE_hash_command.format |
|
hostname_发布_hash_command。format |
|
hostname_snap_temp_hash_command。format |
哪里:
-
hostname- 执行命令或 RPC 的设备的主机名。
-
(预览 |发帖 |snap_temp) - 标识作的标记。该
snapcheck
作在当前版本中使用标记PRE
;在早期版本中,该作使用标记snap_temp
。 -
hash- 为包含
rpc
和kwargs
键的测试文件生成kwargs
的哈希值。如果测试文件使用相同的 RPC,但包含不同的参数,并且 RPC 在同一主机上执行,则哈希可确保在这些情况下输出文件名具有唯一性。如果测试文件定义了密钥,
command
或者测试文件定义了密钥但rpc
不包含密钥,kwargs
则省略哈希。 -
command- 在受管设备上执行的命令或 RPC。该模块用下划线 ( _ ) 替换命令或 RPC 名称中的空格和特殊字符。
-
format- 输出的格式,例如 xml。
该 jsnapy
模块仅根据主机名和命令或 RPC 来区分给定作的快照文件名。因此,如果模块使用定义相同命令或 RPC 的测试文件在同一设备上为同一作拍摄快照,则模块将生成具有相同文件名的快照,并且新文件将覆盖旧文件。
例如,如果模块包含action: "snap_pre"
并引用了在设备 dc1a.example.net 和 dc1b.example.net 上执行和 show interfaces terse
命令的show chassis fpc
测试文件,则生成的文件为:
user@ansible-cn:~$ ls jsnapy/snapshots dc1a.example.net_PRE_show_chassis_fpc.xml dc1a.example.net_PRE_show_interfaces_terse.xml dc1b.example.net_PRE_show_chassis_fpc.xml dc1b.example.net_PRE_show_interfaces_terse.xml
如果模块包含action: "snap_post"
并引用在设备 dc1a.example.net 上执行带有kwargs
项interface_name: lo0
的 get-interface-information
RPC 的测试文件,则生成的文件为:
dc1a.example.net_POST_r1w59I99HXxC3u0VXXshbw==_get_interface_information.xml
除了生成快照文件外, jsnapy
模块还可以在模块响应中返回以下键:
-
action
- 模块执行的 JSNAPy作。 -
changed
—指示设备的状态是否发生变化。由于 JSNAPy 只报告状态,因此该值始终false
为 。 -
failed
- 指示 playbook 任务是否失败。 -
msg
—JSNAPy 测试结果。
查看失败的 JSNAPy 测试
对 Junos 设备执行 JSNAPy 测试时,可以通过注册 jsnapy
模块的响应并使用 ansible.builtin.assert
模块检查是否 passPercentage
为 100 来快速验证所有 JSNAPy 测试是否都通过。但是,如果一个或多个测试失败,则如果输出范围很广,则可能很难识别和提取失败的测试。
该 juniper.device.jsnapy
模块提供了以下选项来查看失败的 JSNAPy 测试:
-
jsnapy
callback plugin — 在 playbook 输出后打印失败的 JSNAPy 测试的摘要。 -
dest_dir
module argument — 将失败的 JSNAPy 测试写入指定目录中的文件。
回 jsnapy
调插件使您能够轻松提取和汇总失败的 JSNAPy 测试的信息。当您启用 jsnapy
回调插件并执行包含 JSNAPy 测试的 playbook 时,该插件会在 playbook PLAY RECAP
之后汇总失败的 JSNAPy 测试的信息。
默认情况下, jsnapy
回调插件处于禁用状态。要启用回调插件, jsnapy
请将 callback_whitelist = jsnapy
语句添加到 Ansible 配置文件中。
[defaults] callback_whitelist = jsnapy
当您启用 jsnapy
回调插件并运行 playbook 时,该插件会以人类可读的格式总结失败的 JSNAPy 测试。例如:
... PLAY RECAP **************************************************************** qfx10002-01 : ok=3 changed=0 unreachable=0 failed=1 qfx10002-02 : ok=3 changed=0 unreachable=0 failed=1 qfx5100-01 : ok=1 changed=0 unreachable=0 failed=1 JSNAPy Results for: qfx10002-01 ******************************************* Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with {"peer-as": "64502", "peer-state": "Active", "peer-address": "198.51.100.21"} Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with {"peer-as": "64510", "peer-state": "Idle", "peer-address": "192.168.0.1"} Value of 'oper-status' not 'is-equal' at '//interface-information/physical-interface[normalize-space(admin-status)='up' and logical-interface/address-family/address-family-name ]' with {"oper-status": "down", "name": "et-0/0/18"} JSNAPy Results for: qfx10002-02 ******************************************* Value of 'peer-state' not 'is-equal' at '//bgp-information/bgp-peer' with {"peer-as": "64502", "peer-state": "Active", "peer-address": "198.51.100.21"}
从 juniper.device
1.0.6 版开始,该 juniper.device.jsnapy
模块还支持该 dest_dir
参数。您可以包括 dest_dir
for check
的参数和 snapcheck
根据测试条件评估快照的作。当您执行 check
或 snapcheck
作并包含 dest_dir
参数时,该模块会将给定主机的每个失败的 JSNAPy 测试写入指定输出目录中的文件。
例如,请考虑以下作手册:
--- - name: Verify BGP hosts: bgp_routers connection: local gather_facts: no tasks: - name: Execute snapcheck juniper.device.jsnapy: action: "snapcheck" dir: "~/jsnapy/testfiles" test_files: - "jsnapy_test_file_bgp_states.yaml" - "jsnapy_test_file_bgp_summary.yaml" logfile: "{{ logfile }}" dest_dir: "{{ playbook_dir }}/jsnapy_failed_tests" register: snapcheck_result
执行 playbook 时,该模块会在给定主机上的每个失败测试的目录中 dest_dir
生成一个文件。例如,为主机 r1 和 r3 上的失败 bgp_neighbor
和 bgp_summary
测试生成以下文件。
user@ansible-cn:~/ansible$ ls jsnapy_failed_tests r1_bgp_neighbor_False.text r3_bgp_neighbor_False.text r1_bgp_summary_False.text r3_bgp_summary_False.text
示例:使用 Ansible 执行 JSNAPy 快照检查作
该 juniper.device.jsnapy
模块允许您在 Ansible作指南中对 Junos 设备执行 JSNAPy 测试。此示例使用 jsnapy
该模块执行作, snapcheck
以在应用特定配置更改后验证 Junos 设备的作状态。
要求
此示例使用以下硬件和软件组件:
-
Ansible 控制节点正在运行:
-
Python 3.8 或更高版本
-
安装了集合的 Ansible 2.18 或更高版本
juniper.device
-
Junos PyEZ 2.7.1 或更高版本
-
Python 1.3.6 或更高版本中的 Junos Snapshot 管理员
-
在执行 Ansible作手册之前,请确保您具备以下条件:
-
启用了 NETCONF over SSH 且用户帐户配置了相应权限的 Junos 设备
-
为 Ansible 控制节点和 Junos 设备上的相应用户配置的 SSH 公钥/私钥对
-
定义了所需主机的现有 Ansible 清单文件
概述
在此示例中,Ansible作指南在三个 Junos 设备上配置 BGP 对等会话,并使用该jsnapy
模块验证是否已为每个邻居地址建立了 BGP 会话。如果作指南验证会话已在设备上建立,它将确认新配置的提交。如果作指南未确认提交,Junos 设备会自动回滚到之前提交的配置。Ansible 项目分别在和 host_vars
目录下group_vars
定义了作指南的组变量和主机变量。
剧本有两出戏。第一次播放 Load and commit BGP configuration
,生成并组合配置,在设备上加载配置,并使用提交确认作进行提交。如果配置已更新,则会通知一个处理程序。该剧执行以下任务:
Remove build directory |
删除给定设备的现有内部版本目录(如果存在)。 |
Create build directory |
为给定设备创建一个新的空生成目录。 |
Build BGP configuration |
使用带有 Jinja2 模板和主机变量的 |
Assemble configuration parts |
使用模块 在此示例中,将仅显示 BGP 配置文件,因此生成的配置文件与上一个任务中呈现的 BGP 配置文件相同。如果稍后添加新任务以从其他模板生成其他配置文件,则 |
Load and commit config, require confirmation |
将配置加载到 Junos 设备上,并使用作 如果设备上已存在请求的配置, |
第二个重头戏 Verify BGP
,使用 JSNAPy 测试文件中的测试在每个设备上执行 JSNAPy snapcheck
作。如果所有测试都通过,则播放也会确认提交。该剧执行以下任务:
Execute snapcheck |
执行 JSNAPy 在此示例中,playbook 通过将参数设置为 |
Confirm commit |
执行提交检查作,以确认之前的提交作,前提是第一个 playbook play 更新了配置,并且所有 JSNAPy 测试都通过了。如果作指南更新了配置,但未确认提交,Junos 设备会自动将配置回滚到之前提交的配置。
注意:
您可以使用设备上的 或 |
Verify BGP configuration |
(选答)明确指示给定设备上的 JSNAPy 测试是通过还是失败。此任务不是特别必需的,但它更容易识别 JSNAPy 测试何时失败以及在哪些设备上失败。 |
配置
定义组变量
分步过程
要定义组变量,请执行以下作:
-
在 group_vars/all 文件中,为构建目录以及配置和日志文件的文件名定义变量。
build_dir: "{{ playbook_dir }}/build_conf/{{ inventory_hostname }}" junos_conf: "{{ build_dir }}/junos.conf" logfile: "junos.log"
定义 Jinja2 模板和主机变量
定义 Jinja2 模板
要创建用于生成 BGP 配置的 Jinja2 模板,请执行以下作:
在项目的 playbook 目录中创建名为 bgp-template.j2 的文件。
将 BGP 配置模板添加到文件中。
interfaces { {% for neighbor in neighbors %} {{ neighbor.interface }} { unit 0 { description "{{ neighbor.name }}"; family inet { address {{ neighbor.local_ip }}/30; } } } {% endfor %} lo0 { unit 0 { family inet { address {{ loopback }}/32; } } } } protocols { bgp { group underlay { import bgp-in; export bgp-out; type external; local-as {{ local_asn }}; multipath multiple-as; {% for neighbor in neighbors %} neighbor {{ neighbor.peer_ip }} { peer-as {{ neighbor.asn }}; } {% endfor %} } } lldp { {% for neighbor in neighbors %} interface "{{ neighbor.interface }}"; {% endfor %} } } routing-options { router-id {{ loopback }}; forwarding-table { export bgp-ecmp; } } policy-options { policy-statement bgp-ecmp { then { load-balance per-packet; } } policy-statement bgp-in { then accept; } policy-statement bgp-out { then { next-hop self; accept; } } }
定义主机变量
要定义与 Jinja2 模板一起用于生成 BGP 配置的主机变量,请执行以下作:
在项目的 host_vars 目录中,为每个主机创建一个名为 hostname.yaml 的单独文件。
在 r1.yaml 文件中定义主机 r1 的变量。
--- loopback: 192.168.0.1 local_asn: 64521 neighbors: - interface: ge-0/0/0 name: to-r2 asn: 64522 peer_ip: 198.51.100.2 local_ip: 198.51.100.1 peer_loopback: 192.168.0.2 - interface: ge-0/0/1 name: to-r3 asn: 64523 peer_ip: 198.51.100.6 local_ip: 198.51.100.5 peer_loopback: 192.168.0.3
在 r2.yaml 文件中定义主机 r2 的变量。
--- loopback: 192.168.0.2 local_asn: 64522 neighbors: - interface: ge-0/0/0 name: to-r1 asn: 64521 peer_ip: 198.51.100.1 local_ip: 198.51.100.2 peer_loopback: 192.168.0.1 - interface: ge-0/0/1 name: to-r3 asn: 64523 peer_ip: 198.51.100.10 local_ip: 198.51.100.9 peer_loopback: 192.168.0.3
在 r3.yaml 文件中定义主机 r3 的变量。
--- loopback: 192.168.0.3 local_asn: 64523 neighbors: - interface: ge-0/0/0 name: to-r1 asn: 64521 peer_ip: 198.51.100.5 local_ip: 198.51.100.6 peer_loopback: 192.168.0.1 - interface: ge-0/0/1 name: to-r2 asn: 64522 peer_ip: 198.51.100.9 local_ip: 198.51.100.10 peer_loopback: 192.168.0.2
创建 JSNAPy 测试文件
分步过程
该 jsnapy
模块引用 ~/jsnapy/testfiles 目录中的 JSNAPy 测试文件。要创建 JSNAPy 测试文件,请执行以下作:
创建 jsnapy_test_file_bgp_states.yaml 文件,该文件将
show bgp neighbor
执行命令并测试是否建立了BGP 对等体状态。bgp_neighbor: - command: show bgp neighbor - ignore-null: true - iterate: xpath: '//bgp-peer' id: './peer-address' tests: # Check if peers are in the established state - is-equal: peer-state, Established err: "Test Failed!! peer <{{post['peer-address']}}> state is not Established, it is <{{post['peer-states']}}>" info: "Test succeeded!! peer <{{post['peer-address']}}> state is <{{post['peer-state']}}>"
创建 jsnapy_test_file_bgp_summary.yaml 文件,该文件将
show bgp summary
执行命令并断言 BGP 向下对等方计数必须为 0。bgp_summary: - command: show bgp summary - item: xpath: '/bgp-information' tests: - is-equal: down-peer-count, 0 err: "Test Failed!! down-peer-count is not equal to 0. It is equal to <{{post['down-peer-count']}}>" info: "Test succeeded!! down-peer-count is equal to <{{post['down-peer-count']}}>"
创建 Ansible 指南
定义配置设备的第一个重头戏
要创建第一次播放,这将呈现配置,将其加载到设备上,并将配置提交为提交确认作:
包括 playbook 和第一个 play(在本地执行模块)的样板。
--- - name: Load and commit BGP configuration hosts: bgp_routers connection: local gather_facts: no
创建任务,将现有构建目录替换为空目录,该目录将存储新的配置文件。
tasks: - name: Remove build directory file: path: "{{ build_dir }}" state: absent - name: Create build directory file: path: "{{ build_dir }}" state: directory
创建从 Jinja2 模板文件和主机变量呈现 BGP 配置的任务,并将其存储在该主机的构建目录中的 bgp.conf 文件中。
- name: Build BGP configuration template: src: "{{ playbook_dir }}/bgp-template.j2" dest: "{{ build_dir }}/bgp.conf"
创建一个任务,将构建目录中的配置文件组装到最终的 junos.conf 配置文件中。
- name: Assemble configuration parts assemble: src: "{{ build_dir }}" dest: "{{ junos_conf }}"
创建任务,用于在设备上加载配置,执行需要确认的提交作,并通知给定的处理程序(前提是配置已更改)。
- name: Load and commit config, require confirmation juniper.device.config: load: "merge" format: "text" src: "{{ junos_conf }}" confirm: 5 comment: "config by Ansible" logfile: "{{ logfile }}" register: config_result # Notify handler, only if configuration changes. notify: - Waiting for BGP peers to establish connections
创建一个处理程序,该处理程序在设备配置更新时暂停 playbook 执行。将暂停时间设置为适合您的环境的值。
handlers: - name: Waiting for BGP peers to establish connections pause: seconds=60
定义执行 JSNAPy作的第二次播放
要创建第二个重头戏,它将执行 JSNAPy 快照检查作并确认提交的配置,前提是配置已更改且 JSNAPy 测试通过:
包括第二个播放的样板,该样板在本地执行模块。
- name: Verify BGP hosts: bgp_routers connection: local gather_facts: no
创建一个任务以根据给定 JSNAPy 测试文件中的测试执行 JSNAPy 快照检查作,并注册模块的响应。
tasks: - name: Execute snapcheck juniper.device.jsnapy: action: "snapcheck" dir: "~/jsnapy/testfiles" test_files: - "jsnapy_test_file_bgp_states.yaml" - "jsnapy_test_file_bgp_summary.yaml" logfile: "{{ logfile }}" register: snapcheck_result
创建任务以确认提交,前提是满足给定条件。
# Confirm commit only if configuration changed and JSNAPy tests pass - name: Confirm commit juniper.device.config: check: true commit: false diff: false logfile: "{{ logfile }}" when: - config_result.changed - "snapcheck_result.passPercentage == 100"
(选答)创建一个任务,该任务使用模块
ansible.builtin.assert
来断言 JSNAPy 测试已通过。- name: Verify BGP configuration ansible.builtin.assert: that: - "snapcheck_result.passPercentage == 100" msg: "JSNAPy test on {{ inventory_hostname }} failed"
结果
在 Ansible 控制节点上,查看已完成的作指南。如果 playbook 未显示预期的代码,请重复本节中的说明以更正 playbook。
--- - name: Load and commit BGP configuration hosts: bgp_routers connection: local gather_facts: no tasks: - name: Remove build directory file: path: "{{ build_dir }}" state: absent - name: Create build directory file: path: "{{ build_dir }}" state: directory - name: Build BGP configuration template: src: "{{ playbook_dir }}/bgp-template.j2" dest: "{{ build_dir }}/bgp.conf" - name: Assemble configuration parts assemble: src: "{{ build_dir }}" dest: "{{ junos_conf }}" - name: Load and commit config, require confirmation juniper.device.config: load: "merge" format: "text" src: "{{ junos_conf }}" confirm: 5 comment: "config by Ansible" logfile: "{{ logfile }}" register: config_result # Notify handler, only if configuration changes. notify: - Waiting for BGP peers to establish connections handlers: - name: Waiting for BGP peers to establish connections pause: seconds=60 - name: Verify BGP hosts: bgp_routers connection: local gather_facts: no tasks: - name: Execute snapcheck juniper.device.jsnapy: action: "snapcheck" dir: "~/jsnapy/testfiles" test_files: - "jsnapy_test_file_bgp_states.yaml" - "jsnapy_test_file_bgp_summary.yaml" logfile: "{{ logfile }}" register: snapcheck_result # Confirm commit only if configuration changed and JSNAPy tests pass - name: Confirm commit juniper.device.config: check: true commit: false diff: false logfile: "{{ logfile }}" when: - config_result.changed - "snapcheck_result.passPercentage == 100" - name: Verify BGP configuration ansible.builtin.assert: that: - "snapcheck_result.passPercentage == 100" msg: "JSNAPy test on {{ inventory_hostname }} failed"
执行作手册
要执行 playbook,请执行以下作:
-
在控制节点上发出
ansible-playbook
命令,并提供作指南路径和所需的任何选项。user@ansible-cn:~/ansible$ ansible-playbook ansible-pb-bgp-configuration.yaml PLAY [Load and commit BGP configuration] ************************************* TASK [Remove build directory] ************************************************ changed: [r1] changed: [r2] changed: [r3] TASK [Create build directory] ************************************************ changed: [r1] changed: [r2] changed: [r3] TASK [Build BGP configuration] *********************************************** changed: [r2] changed: [r1] changed: [r3] TASK [Assemble configuration parts] ****************************************** changed: [r3] changed: [r2] changed: [r1] TASK [Load and commit config, require confirmation] ************************** changed: [r2] changed: [r1] changed: [r3] RUNNING HANDLER [Waiting for BGP peers to establish connections] ************* Pausing for 60 seconds (ctrl+C then 'C' = continue early, ctrl+C then 'A' = abort) ok: [r3]
PLAY [Verify BGP] ************************************************************ TASK [Execute snapcheck] ***************************************************** ok: [r2] ok: [r1] ok: [r3] TASK [Confirm commit] ******************************************************** ok: [r2] ok: [r1] ok: [r3] TASK [Verify BGP configuration] ********************************************** ok: [r1] => { "changed": false, "msg": "All assertions passed" } ok: [r2] => { "changed": false, "msg": "All assertions passed" } ok: [r3] => { "changed": false, "msg": "All assertions passed" } PLAY RECAP ******************************************************************* r1 : ok=8 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 r2 : ok=8 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 r3 : ok=9 changed=5 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
验证
验证 BGP 邻接方
目的
验证是否已为每个邻居地址建立 BGP 会话。
JSNAPy 测试文件测试是否为每个邻接方地址建立了 BGP 会话,以及是否存在关闭对等方。 Verify BGP configuration
任务输出使您能够快速验证给定设备是否通过了所有 JSNAPy 测试。如果 JSNAPy passPercentage
等于 100%,则任务包含在 "msg": "All assertions passed"
任务输出中。
行动
Verify BGP configuration
查看任务输出,并验证每个设备是否返回消息All assertions passed
。
TASK [Verify BGP configuration] ********************************************** ok: [r1] => { "changed": false, "msg": "All assertions passed" } ok: [r2] => { "changed": false, "msg": "All assertions passed" } ok: [r3] => { "changed": false, "msg": "All assertions passed" }
意义
该 All assertions passed
消息指示已在设备上成功建立 BGP 会话。
Ansible Playbook 故障排除
配置加载错误疑难解答
问题
Ansible作指南将生成一个 ConfigLoadError
错误,指示由于语法错误而无法在设备上加载配置。
fatal: [r1]: FAILED! => {"changed": false, "msg": "Failure loading the configuraton: ConfigLoadError(severity: error, bad_element: protocol, message: error: syntax error\nerror: error recovery ignores input until this point)"}
溶液
该作指南使用 Jinja2 模板和 host_vars 目录中为该设备定义的主机变量来呈现 Junos OS 配置。当 Jinja2 模板生成无效配置时,playbook 会生成语法错误。若要更正此错误,请更新 Jinja2 模板以更正错误消息中键 bad_element
标识的元素。
对失败的 JSNAPy 测试进行故障排除
问题
Verify BGP configuration
任务输出指示断言失败,因为 JSNAPy passPercentage
不等于 100%。
TASK [Verify BGP configuration] ************************************************************* fatal: [r1]: FAILED! => { "assertion": "snapcheck_result.passPercentage == 100", "changed": false, "evaluated_to": false, "msg": "JSNAPy test on r1 failed" }
当设备尚未与其邻居建立 BGP 会话或会话中断时,断言将失败。如果断言失败,并且该设备的配置在第一次播放中已更新,则作指南不会确认设备上新配置的提交,并且设备会将配置回滚到之前提交的配置。
溶液
如果在对等方建立会话之前执行该 snapcheck
作,或者由于 BGP 邻接方配置不正确,则 JSNAPy 测试可能会失败。如果 playbook 输出指示配置已成功加载并在设备上提交,请尝试将处理程序的暂停间隔增加到适合您的环境的值,然后重新运行 playbook。
handlers: - name: Waiting for BGP peers to establish connections pause: seconds=75
如果测试仍然失败,请验证每个设备的 Jinja2 模板和主机变量是否包含正确的数据,以及每个设备的结果配置是否正确。
提交确认失败疑难解答
问题
未在一台或多台设备上确认配置。
TASK [Confirm commit] *********************************************************************** skipping: [r2] skipping: [r2] skipping: [r3]
溶液
仅当配置发生更改且 JSNAPy 测试通过时,作指南才会确认配置。 Load and commit config, require confirmation
如果任务输出指示配置未更改,则 playbook 不会执行任务来确认提交。如果配置有更改但未得到确认,则 JSNAPy 测试将失败。如果 BGP 邻接方配置不正确,或者作指南未在两次播放之间为设备提供足够的时间来建立 BGP 会话,则 JSNAPy 测试可能会失败。有关更多信息,请参阅 对失败的 JSNAPy 测试进行故障排除。