Ansible プレイブックで Python で Junos Snapshot Administrator(JSNAPy)を使用する
概要 Ansibleプレイブックの一部としてJSNAPyテストを実行し、Junosデバイスのランタイム環境スナップショットをキャプチャして監査します。
PythonのJunos® Snapshotアドミニストレータ(JSNAPy)を使用すると、Junosデバイスのランタイム環境スナップショットをキャプチャして監査できます。デバイスの設定と動作ステータスをキャプチャして検証し、デバイスへの変更を検証できます。ジュニパーネットワークスは、Ansible プレイブックの一部として、Junos デバイスに対して JSNAPy テストを実行するために使用できる Ansible モジュールを提供しています。 表 1 は、使用可能なモジュールの概要を示しています。
コンテンツ セット |
モジュール名 |
---|---|
juniper.device.jsnapy
モジュールを使用するには、Python の Ansible 制御ノードに Junos Snapshot Administrator をインストールする必要があります。インストール手順と、JSNAPy 設定およびテスト ファイルの作成方法については、Python のドキュメントの Junos Snapshot Administrator を参照してください。
次のセクションでは、Ansible Playbook で juniper.device.jsnapy
モジュールを使用する方法について説明します。
モジュールの概要
juniper.device.jsnapy
モジュールを使用すると、次のようなJSNAPy機能をAnsibleプレイブック内から実行できます。
-
ランタイム環境スナップショットのキャプチャーと保存
-
2 つのスナップショットの比較
-
スナップショットをキャプチャしてすぐに評価する
モジュールでは、 action
引数と、 config_file
または test_files
のいずれかの引数を指定する必要があります。 action
引数は、実行するJSNAPyアクションを指定します。 表 2 は、有効な action
値と同等の JSNAPy コマンドの概要を示しています。
action 値 |
形容 |
同等の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 Playbook ディレクトリー内のファイルをチェックします。ファイルがプレイブックディレクトリに存在しない場合、モジュールはdir
引数ディレクトリ(指定されている場合)または/etc/jsnapy/testfilesディレクトリ(dir
引数が省略されている場合)をチェックインします。ファイルが見つからない場合、Playbook はエラーメッセージを生成します。
dir
パラメーターを含めると、モジュールは指定された config_file
または test_files
引数についてのみその場所をチェックすることに注意してください。したがって、構成ファイルを指定しても、モジュールは、構成ファイル内で指定したテスト・ファイルのdir
・ディレクトリーをチェックしません。構成ファイルがテストファイルの相対パスを参照する場合、モジュールは Playbook ディレクトリとデフォルトの 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
パラメーターを使用して、使用する個々のテスト ファイルを指定することもできます。次のプレイブックは、前のプレイブックの例と同じテストを実行します。この場合、モジュールは最初に 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 です。
モジュールは、モジュールが hosts
セクションを含む構成ファイルを参照している場合でも、Ansible Playbook で指定されたホストで要求されたアクションを実行します。エラーが発生し、JSNAPy テストの実行に失敗した場合、モジュールは失敗を報告します。1 つ以上の JSNAPy テストが失敗した場合は、失敗は報告 されません 。JSNAPy テスト結果を確認するには、モジュールの応答を登録し、 ansible.builtin.assert
モジュールを使用して応答の予期される結果を確認します。
PythonのJunos Snapshot Administratorは、デフォルトでその操作に関する情報を /var/log/jsnapy/jsnapy.log ファイルに記録します。 juniper.device.jsnapy
モジュールには、オプションで logfile
引数を含めることができ、特定のタスクの情報が記録される Ansible 制御ノード上の書き込み可能なファイルへのパスを指定します。Ansible の verbosity level と debug オプションによって、ファイルに記録される情報のレベルが決まります。デフォルトでは、重大度レベルが WARNING 以上のメッセージのみがログに記録されます。重大度レベル INFO または重大度レベル DEBUG 以上のメッセージをログに記録するには、 -v
または -vv
コマンドラインオプションを使用して Playbook をそれぞれ実行します。
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構成ファイルを参照し、プレイブックディレクトリ内の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
モジュールを使用して応答で期待される結果を確認します。
次のプレイブックは、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 snapcheck 操作を実行できます。
スナップショットを取得し、テスト ファイルの 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 snapshotsディレクトリに自動的に保存されます。モジュールは、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)。
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-information
RPC を実行するテスト ファイルを参照する場合、結果のファイルは次のようになります。
dc1a.example.net_POST_r1w59I99HXxC3u0VXXshbw==_get_interface_information.xml
スナップショット ファイルの生成に加えて、 jsnapy
モジュールはモジュール応答で次のキーを返すこともできます。
-
action
- モジュールによって実行されたJSNAPyアクション。 -
changed
- デバイスの状態が変更されたかどうかを示します。JSNAPy は状態のみを報告するため、値は常にfalse
になります。 -
failed
- プレイブック タスクが失敗したかどうかを示します。 -
msg
—JSNAPy テスト結果。
失敗したJSNAPyテストの確認
Junosデバイスに対してJSNAPyテストを実行する場合は、 jsnapy
モジュールの応答を登録し、 ansible.builtin.assert
モジュールを使用して passPercentage
が100であることを確認することで、すべてのJSNAPyテストに合格したかどうかをすばやく検証できます。ただし、1 つ以上のテストが失敗した場合、出力が広範囲に及ぶと、失敗したテストを特定して抽出することが困難な場合があります。
juniper.device.jsnapy
モジュールには、失敗した JSNAPy テストを表示するための次のオプションが用意されています。
-
jsnapy
callback plugin:プレイブックの出力後に、失敗した JSNAPy テストの概要を出力します。 -
dest_dir
module 引数:失敗した JSNAPy テストを指定されたディレクトリ内のファイルに書き込みます。
jsnapy
コールバック プラグインを使用すると、失敗した JSNAPy テストの情報を簡単に抽出して要約できます。jsnapy
コールバック プラグインを有効にし、JSNAPy テストを含むプレイブックを実行すると、プラグインはプレイブックのPLAY RECAP
後に失敗した JSNAPy テストの情報を要約します。
jsnapy
コールバックプラグインはデフォルトで無効になっています。jsnapy
コールバックプラグインを有効にするには、callback_whitelist = jsnapy
ステートメントをAnsible構成ファイルに追加します。
[defaults] callback_whitelist = 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
引数もサポートしています。dest_dir
引数は、テスト条件に対してスナップショットを評価するcheck
およびsnapcheck
操作に含めることができます。check
または snapcheck
操作を実行し、dest_dir
引数を含めると、モジュールは、指定されたホストの失敗した各 JSNAPy テストを、指定された出力ディレクトリ内のファイルに書き込みます。
たとえば、次の Playbook について考えてみます。
--- - 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 Snapcheck操作の実行
juniper.device.jsnapy
モジュールを使用すると、Ansible プレイブックの一部として、Junos デバイスに対して JSNAPy テストを実行できます。この例では、jsnapy
モジュールを使用して、特定の設定変更を適用した後に Junos デバイスの動作状態を検証するsnapcheck
アクションを実行します。
必要条件
この例では、以下のハードウェアとソフトウェアのコンポーネントを使用しています。
-
以下を実行しているAnsibleコントロールノード:
-
Python 3.8 以降
-
Ansible 2.10 以降 (
juniper.device
コレクションがインストールされている) -
Junos PyEZ リリース 2.7.1 以降
-
Junos Snapshot Administrator(Python リリース 1.3.6 以降)
-
Ansibleプレイブックを実行する前に、以下を確認してください。
-
SSH経由のNETCONFが有効で、適切な権限で設定されたユーザーアカウントを持つJunosデバイス
-
Ansible制御ノードとJunosデバイス上の適切なユーザー向けに設定されたSSH公開/秘密キーペア
-
必要なホストが定義された既存のAnsibleインベントリファイル
概要
この例では、Ansible プレイブックが 3 台の Junos デバイスで BGP ピアリング セッションを設定し、 jsnapy
モジュールを使用して、各ネイバー アドレスに対して BGP セッションが確立されていることを確認します。プレイブックは、セッションがデバイスで確立されていることを確認すると、新しい設定のコミットを確認します。プレイブックがコミットを確認しない場合、Junos デバイスは自動的に以前にコミットされた設定にロールバックします。Ansible プロジェクトは、 group_vars
ディレクトリーと host_vars
ディレクトリーの下にある Playbook のグループ変数とホスト変数をそれぞれ定義します。
プレイブックには 2 つのプレイがあります。最初のプレイ Load and commit BGP configuration
では、コンフィギュレーションを生成およびアセンブルし、コンフィギュレーションをデバイスにロードし、コミット確認操作を使用してコミットします。設定が更新されると、1 つのハンドラーに通知されます。このプレイでは、次のタスクが実行されます。
Remove build directory |
指定されたデバイスの既存のビルド ディレクトリがある場合は、それを削除します。 |
Create build directory |
指定されたデバイスに対して、新しい空のビルド ディレクトリを作成します。 |
Build BGP configuration |
|
Assemble configuration parts |
この例では、BGP構成ファイルのみが存在するため、結果の構成ファイルは、前のタスクでレンダリングされたBGP構成ファイルと同じになります。後で新しいタスクを追加して他のテンプレートから追加の構成ファイルを生成すると、 |
Load and commit config, require confirmation |
設定を Junos デバイスに読み込み、 要求された設定がすでにデバイスに存在する場合、 |
2 番目のプレイ Verify BGP
では、JSNAPy テスト ファイル内のテストを使用して、各デバイスで JSNAPy snapcheck
操作を実行します。すべてのテストに合格すると、プレイもコミットを確認します。このプレイでは、次のタスクが実行されます。
Execute snapcheck |
JSNAPy この例では、プレイブックは 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 テンプレートを作成するには、次の手順に従います。
プロジェクトの 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; } } }
ホスト変数の定義
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']}}>"
show bgp summary
コマンドを実行し、BGP ダウン ピア カウントを 0 でなければならないことをアサートする jsnapy_test_file_bgp_summary.yaml ファイルを作成します。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 の定型文と、モジュールをローカルで実行する最初のプレイを含めます。
--- - 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 操作を実行する 2 番目のプレイを定義します
設定が変更され、JSNAPy テストに合格した場合に、JSNAPy snapcheck 処理を実行し、コミットされた設定を確認する 2 番目のプレイを作成するには、次の手順に従います。
モジュールをローカルで実行する 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"
プレイブックを実行する
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 テンプレートが無効な設定を生成する場合、構文エラーを生成します。このエラーを修正するには、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 テンプレートとホスト変数に正しいデータが含まれていること、および各デバイスの結果の構成が正しいことを確認します。
失敗したコミット確認のトラブルシューティング
問題
1 つ以上のデバイスで設定が確認されませんでした。
TASK [Confirm commit] *********************************************************************** skipping: [r2] skipping: [r2] skipping: [r3]
解決
プレイブックは、設定が変更され、JSNAPy テストに合格した場合にのみ、設定を確認します。 Load and commit config, require confirmation
タスクの出力に構成が変更されなかったことが示されている場合、Playbook はコミットを確認するためのタスクを実行しません。設定が変更されても確認されなかった場合、JSNAPy テストは失敗します。BGP ネイバーが正しく設定されていない場合、または デバイスが BGP セッションを確立するための十分な時間がプレイブックにない場合、 JSNAPy テストが失敗することがあります。詳細については、「 失敗したJSNAPyテストのトラブルシューティング」を参照してください。