Ansible PlaybookでPython(JSNAPy)でJunos Snapshot Administratorを使用する
Ansibleプレイブックの一部としてJSNAPyテストを実行し、Junosデバイスのランタイム環境スナップショットをキャプチャして監査します。
PythonのJunos®スナップショットアドミニストレーター(JSNAPy)を使用すると、Junosデバイスのランタイム環境スナップショットをキャプチャして監査できます。デバイスの設定と運用ステータスを取得して検証し、デバイスへの変更を検証できます。ジュニパーネットワークスには、Ansible プレイブックの一部として、Junos デバイスに対する JSNAPy テストの実行に使用できる Ansible モジュールが用意されています。 表1は 、利用可能なモジュールの概要を示しています。
|
コレクション |
モジュールセット |
モジュール名 |
|---|---|---|
|
|
Junos juniper.device.jsnapy モジュールを使用するには、AnsibleコントロールノードにPythonでSnapshot Administratorをインストールする必要があります。JSNAPy の設定ファイルとテスト ファイルのインストール手順と作成方法については、 Python ドキュメントの Junos Snapshot Administrator を参照してください。
以下のセクションでは、Ansible プレイブックで juniper.device.jsnapy モジュールを使用する方法について説明します。
モジュールの概要
juniper.device.jsnapyモジュールでは、Ansibleプレイブック内から次のようなJSNAPy機能を実行できます。
-
ランタイム環境スナップショットのキャプチャと保存
-
2つのスナップショットの比較
-
スナップショットをキャプチャして即座に評価
モジュールでは、 action 引数と config_file 引数または test_files 引数を指定する必要があります。 action 引数は、実行するJSNAPyアクションを指定します。 表2は 、有効な action 値と同等のJSNAPyコマンドの概要を示しています。
|
|
説明 |
同等のJSNAPyコマンド |
|---|---|---|
|
|
指定されたテストケースに基づいて2つの既存のスナップショットを比較するか、テストケースが提供されていない場合は、スナップショットをノードごとに比較します。 |
|
|
|
指定されたデバイスに変更を加えた後、テストファイルで指定されたコマンドまたはRPCのスナップショットを作成します。 |
|
|
|
指定されたデバイスに変更を加える前に、テストファイルで指定されたコマンドまたはRPCのスナップショットを作成します。 |
|
|
|
テストファイルで指定されたコマンドまたはRPCのスナップショットを取得し、テストケースで事前に定義した基準に照らし合わせてスナップショットを即座に評価します。 |
|
コマンドラインでJSNAPyを実行すると、JSNAPyは設定ファイルの hosts セクションで指定されたホスト上で要求されたアクションを実行します。一方、Ansibleモジュールは、Ansibleプレイブックで指定されたホスト上で要求されたアクションを実行します。その結果、モジュールは、 hosts セクションを無視して設定ファイルを参照することも、1つ以上のテストファイルを直接参照することもできます。
したがって、juniper.device.jsnapyモジュールでは、action引数に加えて、特定のアクションに使用するJSNAPy設定ファイルまたはJSNAPyテストファイルを指定するために、config_file引数またはtest_files引数のいずれかも必要になります。表3は、config_file引数とtest_files引数の概要を示しています。
|
モジュール引数 |
値 |
追加情報 |
|---|---|---|
|
|
JSNAPy設定ファイルへの絶対ファイルまたは相対ファイルパス。 |
パスが相対パスの場合、モジュールは以下の場所と指定された順序で設定ファイルをチェックします。
設定ファイルが相対ファイルパスを使用してテストファイルを参照している場合、モジュールはまずプレイブックディレクトリ内のテストファイルを確認します。次に、デフォルトの |
|
|
JSNAPyテストファイルへの絶対または相対ファイルパス。この値は、単一のファイルパスまたはファイルパスのリストです。 |
相対パスを指定する各テストファイルについて、モジュールは以下の場所と指定された順序でファイルを検査します。
|
config_file引数とtest_files引数は、絶対ファイルパスまたは相対ファイルパスを取ることができます。相対ファイルパスを使用する場合は、オプションでdir モジュール引数を含めて、ファイルが存在するディレクトリを指定できます。config_file引数またはtest_files引数が相対ファイルパスを使用している場合、モジュールは、dir引数が存在する場合でも、まずAnsibleプレイブックディレクトリ内のファイルを確認します。ファイルがプレイブック・ディレクトリーに存在しない場合、モジュールはdir引数ディレクトリー(指定されている場合は)または/etc/jsnapy/testfilesディレクトリー(dir引数が省略されている場合)をチェックします。ファイルが見つからない場合、プレイブックはエラーメッセージを生成します。
dir パラメーターを含めると、モジュールは指定された config_file または test_files 引数についてのみその場所を確認することに注意することが重要です。そのため、設定ファイルを指定しても、モジュールは設定ファイル内で指定したテストファイルのdirディレクトリをチェックしません。設定ファイルがテストファイルの相対パスを参照している場合、モジュールはプレイブックディレクトリとデフォルトのtestfilesディレクトリ内でのみテストファイルをチェックします。
~/jsnapy/testfilesディレクトリに存在し、複数のJSNAPyテストファイルを参照しているJSNAPy設定ファイルjsnapy_config_base_tests.yamlがあるとします。
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
以下のサンプルプレイブックは、jsnapy_config_base_tests.yaml設定ファイル内の各テストファイルに対してsnap_preアクションを実行します。設定ファイルがプレイブックディレクトリに存在しない場合、モジュールは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 パラメーターを使用して、使用する個々のテストファイルを指定できます。次のプレイブックでは、前のプレイブックの例と同じテストを実行します。この場合、モジュールはまずプレイブックディレクトリ内のテストファイルを確認し、次に 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 です。
モジュールは、モジュールが hosts セクションを含む設定ファイルを参照している場合でも、Ansibleプレイブックで指定されたホスト上で要求されたアクションを実行します。エラーが発生し、JSNAPy テストの実行に失敗した場合、モジュールは失敗を報告します。1つ以上のJSNAPyテストが失敗しても、失敗は報告 されません 。JSNAPyテスト結果を確認するには、モジュールのレスポンスを登録し、 ansible.builtin.assert モジュールを使用してレスポンスで期待される結果を確認します。
JSNAPy は、デフォルトで、その動作に関する情報を /var/log/jsnapy/jsnapy.log ファイルに記録します。 juniper.device.jsnapy モジュールには、オプションで logfile 引数を含めることができます。その値は、Ansible制御ノード上の書き込み可能なファイルへのパスを指定します。Ansibleの詳細レベルとデバッグオプションによって、ファイルに記録される情報のレベルが決まります。デフォルトでは、重大度レベルWARNING以上のメッセージのみがログに記録されます。重大度レベル INFO または重大度レベル DEBUG 以上のメッセージをログに記録するには、それぞれ -v または -vv コマンドラインオプションを使用してプレイブックを実行します。
AnsibleプレイブックでJSNAPyテストを実行するときに、失敗したJSNAPyテストの情報を保存または要約できます。詳細については、「 失敗したJSNAPyテストの確認」を参照してください。
スナップショットを取得して比較する
JSNAPyを使用すると、変更の前後にJunosデバイスのランタイム環境スナップショットを取得し、スナップショットを比較して、予想される変更を検証したり、予期しない問題を特定したりできます。 juniper.device.jsnapy モジュールでは、Ansibleプレイブックの一部としてJSNAPyスナップショットを作成して比較できます。このモジュールは、事前に決められたファイル名を使用して、各ホストの各スナップショットをデフォルトのJSNAPyスナップショットディレクトリ内の個別のファイルに保存します。出力ファイルの詳細については、「 jsnapy モジュール出力について」を参照してください。
変更を行う前に、1つ以上のデバイスのベースラインスナップショットを作成するには:
-
モジュールの
action引数をsnap_preに設定します。 -
設定ファイルまたは1つ以上のテストファイルを指定します。
次のプレイブックでは、Ansibleインベントリグループ内の各デバイスのPREスナップショットを保存します。このタスクは、~/jsnapy/testfilesディレクトリ内のjsnapy_config_base_tests.yaml設定ファイルを参照し、プレイブックディレクトリ内の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"
変更を実行した後に1つ以上のデバイスのスナップショットを作成するには:
-
モジュールの
action引数をsnap_postに設定します。 -
設定ファイルまたは1つ以上のテストファイルを指定します。
次のプレイブックは、Ansibleインベントリグループ内の各デバイスのPOSTスナップショットを保存します。このタスクは、~/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"
juniper.device.jsnapyモジュールがsnap_preアクションまたはsnap_postアクションを実行すると、それぞれ「PRE」または「POST」タグを含む自動生成されたファイル名を使用して、各ホストの各スナップショットを個別のファイルに保存します。checkアクションを実行してPREスナップショットとPOSTスナップショットを比較し、更新を迅速に確認したり、変更によって生じた可能性のある問題を特定したりできます。
モジュールが check アクションを実行すると、JSNAPyは各デバイス上の各テストの PRE スナップショットと POST スナップショットを比較し、テストファイルの tests: セクションで定義された基準に対して評価します。テスト・ファイルでテスト・ケースが定義されていない場合、JSNAPy は代わりにスナップショットをノードごとに比較します。
PRE スナップショットと POST スナップショットを比較するには:
-
モジュールの
action引数をcheckに設定します。 -
スナップショットの作成に使用されたものと同じ設定ファイルまたはテストファイルを指定します。
-
モジュールの応答を登録し、
ansible.builtin.assertモジュールを使用して応答で期待される結果を検証することで、テスト結果を確認します。
次のプレイブックは、Ansibleインベントリグループ内のすべてのデバイスについて、以前に実行された snap_pre アクションと snap_post アクションで取得されたスナップショットを比較したものです。結果は、設定ファイルで参照されているテストファイルの基準を使用して評価されます。プレイブックは、モジュールの応答を「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
Snapcheck操作の実行
JSNAPyを使用すると、JSNAPyテストファイルで指定されたコマンドまたはRPCのスナップショットを取得し、テストケースで事前定義された基準に対してスナップショットを即座に評価できます。 juniper.device.jsnapy モジュールでは、Ansibleプレイブックの一部としてJSNAPyスナップチェック操作を実行できます。
スナップショットを作成し、テストファイルの tests: セクションにある事前定義された基準セットに基づいてすぐに評価するには:
-
モジュールの
action引数をsnapcheckに設定します。 -
設定ファイルまたは1つ以上のテストファイルを指定します。
-
モジュールの応答を登録し、
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.cfg) を変更して別の場所を指定しない限り、モジュールはデフォルトの JSNAPy ディレクトリを使用します。このモジュールは、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_POST_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 など)。
juniper.device.jsnapyモジュールは、ホスト名とコマンドまたはRPCのみに基づいて、特定のアクションのスナップショットファイル名を区別します。その結果、モジュールが同じコマンドまたはRPCを定義するテストファイルを使用して、同じアクションに対して同じデバイス上でスナップショットを取得すると、モジュールは同じファイル名のスナップショットを生成し、新しいファイルは古いファイルを上書きします。
たとえば、モジュールに action: "snap_pre" が含まれており、dc1a.example.net デバイスおよび dc1b.example.net デバイス上で show chassis fpc および show interfaces terse コマンドを実行するテストファイルを参照している場合、結果のファイルは次のようになります。
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-informationRPCを実行するテストファイルを参照する場合、結果のファイルは次のようになります。
dc1a.example.net_POST_r1w59I99HXxC3u0VXXshbw==_get_interface_information.xml
スナップショットファイルの生成に加えて、 juniper.device.jsnapy モジュールは、モジュール応答で以下のキーを返すこともできます。
-
action—モジュールによって実行されるJSNAPyアクション。 -
changed- デバイスの状態が変化したかどうかを示します。JSNAPy は状態のみを報告するため、値は常にfalseです。 -
failed—プレイブックタスクが失敗したかどうかを示します。 -
msg—JSNAPyテスト結果。
失敗したJSNAPyテストを確認する
Junosデバイスに対してJSNAPyテストを実行すると、すべてのJSNAPyテストに合格したかどうかをすばやく確認できます。 juniper.device.jsnapy モジュールの応答を登録し、 ansible.builtin.assert モジュールを使用して passPercentage が100であることを確認します。ただし、1 つ以上のテストが失敗した場合、出力が広範囲に及ぶと、失敗したテストを特定して抽出することが困難になる場合があります。
juniper.device.jsnapyモジュールには、失敗したJSNAPyテストを確認するための以下のオプションが用意されています。
-
juniper.device.jsnapyコールバックプラグイン—プレイブックの出力後に失敗したJSNAPyテストの概要を出力します。 -
dest_dirモジュール引数—失敗したJSNAPyテストを指定したディレクトリ内のファイルに書き込みます。
jsnapyコールバックプラグインを使用すると、失敗したJSNAPyテストの情報を簡単に抽出して要約できます。jsnapyコールバックプラグインを有効にし、JSNAPyテストを含むプレイブックを実行すると、プラグインはプレイブックPLAY RECAP後に失敗したJSNAPyテストの情報を要約します。
jsnapyコールバックプラグインはデフォルトで無効になっています。jsnapyコールバックプラグインを有効にするには、Ansible設定ファイルにcallbacks_enabled = juniper.device.jsnapyステートメントを追加します。
[defaults] callbacks_enabled = juniper.device.jsnapy
jsnapyコールバックプラグインを有効にしてプレイブックを実行すると、プラグインは失敗した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引数をサポートするようになりました。テスト基準に照らしてスナップショットを評価するcheckおよびsnapcheck操作には、dest_dir引数を含めることができます。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
プレイブックを実行すると、モジュールは、指定されたホストで失敗したテストごとに、 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 Snapcheck操作を実行する
juniper.device.jsnapyモジュールでは、Ansibleプレイブックの一部として、Junosデバイスに対してJSNAPyテストを実行できます。この例では、jsnapy モジュールを使用して、特定の設定変更を適用した後Junosデバイスの動作状態を検証するためのsnapcheckアクションを実行します。
要件
この例では、以下のハードウェアおよびソフトウェアコンポーネントを使用しています。
-
Ansible制御ノードの実行中:
-
Python 3.10以降
-
juniper.deviceコレクションがインストールされたAnsible 2.17以降 -
Junos PyEZ リリース 2.7.3 以降
-
Pythonリリース1.3.7以降のJunos Snapshot Administrator
-
Ansibleプレイブックを実行する前に、以下を満たしていることを確認してください。
-
NETCONF over SSHが有効で、適切な権限が設定されたユーザーアカウントを備えたJunosデバイス
-
AnsibleコントロールノードとJunosデバイス上の適切なユーザーに設定されたSSHパブリックキー/プライベートキーペア
-
必要なホストが定義された既存のAnsibleインベントリファイル
概要
この例では、Ansibleプレイブックは、3つのJunosデバイスでBGPピアリングセッションを設定し、 jsnapy モジュールを使用して、各ネイバーアドレスに対してBGPセッションが確立されていることを確認します。プレイブックがデバイス上でセッションが確立されていることを確認すると、新しい設定のコミットを確認します。プレイブックがコミットを確認しない場合、Junosデバイスは自動的に以前にコミットされた設定にロールバックします。Ansibleプロジェクトでは、プレイブックのグループ変数とホスト変数をそれぞれ group_vars ディレクトリと host_vars ディレクトリの下に定義します。
プレイブックには2つのプレイがあります。最初のプレイである Load and commit BGP configurationでは、コンフィギュレーションを生成およびアセンブルし、デバイスにコンフィギュレーションを読み込み、コミット確認操作を使用してコミットします。設定が更新されると、1 つのハンドラーが通知されます。劇は以下のタスクを実行します。
Remove build directory |
指定されたデバイスの既存のビルドディレクトリを削除します(存在する場合)。 |
Create build directory |
指定されたデバイスに対して新しい空のビルドディレクトリを作成します。 |
Build BGP configuration |
Jinja2テンプレートとホスト変数とともに |
Assemble configuration parts |
この例では、BGP設定ファイルのみが存在するため、結果の設定ファイルは前のタスクでレンダリングされたBGP設定ファイルと同じになります。後で新しいタスクを追加して他のテンプレートから追加の設定ファイルを生成した場合、 |
Load and commit config, require confirmation |
設定をJunosデバイスにロードし、 要求された設定がデバイス上にすでに存在する場合、 |
2つ目のプレイである Verify BGPでは、JSNAPyテストファイル内のテストを使用して、各デバイス上でJSNAPy snapcheck 操作を実行します。すべてのテストに合格すると、プレイはコミットも確認します。劇は以下のタスクを実行します。
Execute snapcheck |
JSNAPy この例では、プレイブックは |
Confirm commit |
コミットチェック操作を実行します。最初のプレイブックプレイで設定が更新され、すべての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テンプレートを作成するには:
-
プロジェクトのプレイブックディレクトリに 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; } } }
ホスト変数の定義
BGP設定を生成するためにJinja2テンプレートで使用されるホスト変数を定義するには:
-
プロジェクトの 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プレイブックの作成
デバイスを設定するための最初のプレイを定義する
設定をレンダリングし、デバイスにロードし、コミット確認操作として設定をコミットする最初のプレイを作成するには:
-
プレイブックと、モジュールをローカルで実行する最初のプレイの定型文を含めます。
--- - 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 -
デバイス設定が更新された場合にプレイブックの実行を一時停止するハンドラーを作成します。一時停止時間を環境に適した値に設定します。
handlers: - name: Waiting for BGP peers to establish connections pause: seconds=60
JSNAPy操作を実行する2番目のプレイを定義する
JSNAPy スナップチェック操作を実行し、コミットされた構成を確認する 2 番目のプレイを作成するには、構成が変更され、JSNAPy テストに合格した場合に、以下を行います。
-
モジュールをローカルで実行する 2 番目のプレイの定型文を含めます。
- name: Verify BGP hosts: bgp_routers connection: local gather_facts: no
-
指定されたJSNAPyテスト・ファイル内のテストに基づいてJSNAPy snapcheck操作を実行するタスクを作成し、モジュールのレスポンスを登録します。
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コントロールノードで、完成したプレイブックを確認します。プレイブックに意図したコードが表示されない場合は、このセクションの手順を繰り返してプレイブックを修正します。
---
- 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"
プレイブックを実行する
プレイブックを実行するには:
-
制御ノードで
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テンプレートが無効な設定を生成すると構文エラーを生成します。このエラーを修正するには、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 テストが失敗することがあります。プレイブックの出力に、デバイス上で設定が正常に読み込まれ、コミットされたことが示されている場合は、ハンドラーの一時停止間隔を環境に適した値まで増やし、プレイブックを再実行してみてください。
handlers:
- name: Waiting for BGP peers to establish connections
pause: seconds=75
それでもテストが失敗する場合は、各デバイスのJinja2テンプレートとホスト変数に正しいデータが含まれていること、および各デバイスの結果の構成が正しいことを確認します。
失敗したコミット確認のトラブルシューティング
問題点
1つ以上のデバイスで設定が確認されませんでした。
TASK [Confirm commit] *********************************************************************** skipping: [r2] skipping: [r2] skipping: [r3]
ソリューション
プレイブックは、設定が変更され、JSNAPy テストに合格した場合にのみ設定を確認します。 Load and commit config, require confirmation タスクの出力に設定が変更されていないことが示されている場合、プレイブックはコミットを確認するタスクを実行しません。設定が変更されても確認されなかった場合、JSNAPy テストは失敗しました。BGPネイバーが正しく設定されていない場合、またはプレイブックがデバイスがBGPセッションを確立するのに十分なプレイ間隔を提供していない場合、JSNAPy BGPテストは失敗する可能性があります。詳細については、「 失敗したJSNAPyテストのトラブルシューティング」を参照してください。