これは Ansible Advent Calendar 2017 の18日目の記事です。
■ やりたいこと
Ansible で Cisco IOS から複数のIPアドレスに対してpingを実行し、その結果をCSVファイルに出力します。本記事では、利用する ios_ping
モジュールの説明と、 Playbookのサンプルをご紹介します。
■ ios_ping モジュールの説明
ios_ping
はCisco IOS の機器から ping を実行して、ロス率やRTT値など パース して返してくれるモジュールです。Ansible 2.4 で追加されました。(本記事は Ansible 2.4.2 を前提としています)
手作業によるコマンド結果と、パースして取得できる情報の関係は以下の通りです。
主なオプション
ios_ping
モジュール固有のオプションは以下の通りです。
オプション名 | 必須/任意 | デフォルト | 説明 | 対応IOSコマンド書式 | 要特権(*1) |
---|---|---|---|---|---|
dest | 必須 | ping を実行する相手先のIPアドレス、ホスト名です。 | ping [dest] | 要特権 | |
count | 任意 | 5 | ping を実行する回数です。本オプションと、IOSのpingコマンドのタイムアウト(私の環境では2秒)を考慮し、ios_ping モジュールのタスクとしてのタイムアウト( timeout オプション: デフォルト10秒) を設定する必要があります。 |
ping [dest] repeat [count] | 要特権 |
source | 任意 | 送信元の指定です。 | ping [dest] source [source] | 要特権 | |
state | 任意 | present | 想定するping結果の指定です。 想定結果が成功なら present 、失敗なら absent を指定します。成功、失敗の基準は公式ドキュメントに記載されていませんが、ios_ping.pyのコードを見ると「ロス率が100%未満→成功」「ロス率が100%→失敗」ということが分かります。 |
要特権 | |
vrf | 任意 | default | 利用するVRFの指定です。 | ping vrf [vrf] [dest] | 要特権 |
要特権(*1)
と書かれているオプションを利用するには、IOSへログインするユーザーに特権が必要です。手動実行と同じ事情です。- 認証系のオプションである
provider
等は 他のios_command
等のモジュールと共通です。 - 全オプションは ios_ping モジュール公式ドキュメント を参照して下さい。
■ ping結果をCSV出力するためのPlaybookなど
・Playbook
Playbook 本体です。
--- - hosts: ios # インベントリファイルにて10.0.0.1を定義済み gather_facts: no connection: local tasks: - name: ping ios_ping: dest: "{{ item }}" count: 5 # default provider: "{{ cli }}" with_items: - 192.168.1.1 - 192.168.1.2 - 192.168.1.3 - 192.168.1.4 - 192.168.1.5 - 192.168.1.6 - 192.168.1.7 - 192.168.1.8 - 192.168.1.9 - 192.168.1.10 ignore_errors: yes register: result - name: output csv file template: src: ./template_ping_result.txt dest: "./ping_from_{{ inventory_hostname }}_result.csv" vars: cli: host: "{{ inventory_hostname }}" timeout: 15 # (5 * 2) + margin username: testuser password: testpassword authorize: yes auth_pass: testpassword
Playbook の補足説明
with_items
を利用して、複数の宛先へのping結果を取得するようにしています。必要に応じてパラメータ化して下しさい。state
オプションは省略しているため、成功(ロス率100%未満)を想定しています。もしpingが失敗した場合は、playbook中のタスクとしてfailed
扱いになります。- 今回は想定外の
state
になった場合の挙動も確認しつつ、タスクを続行したかったため、少々乱暴ですがignore_errors: yes
を指定しています。 count: 5
(デフォルトと同じ)にしているため、IOS側のpingコマンド仕様のタイムアウト2秒を考慮すると、ロス率100%の宛先相手の場合pingが完了に10秒かかります。タスクとしてのtimeuout
オプションのデフォルトも10秒のため、pingが完了する前にタスクとしてタイムアウトしています。この問題の対策として「count
オプション × pingコマンドタイムアウト = 10秒」にさらに余裕を加えて、ios_ping
モジュールのtimeout
オプションを15
としています。
・テンプレート
ping結果をCSVファイルに整形するするためのテンプレートです。いろいろカスタマイズできます。
"dest","packet_loss","packets_rx","packets_tx","rtt_avg","rtt_max","rtt_min","msg" {% for r in result['results'] %} "{{r['item'] }}","{{ r['packet_loss'] }}",{{ r['packets_rx'] }},{{ r['packets_tx'] }},{{ r['rtt']['avg'] }},{{ r['rtt']['max']}},{{ r['rtt']['min'] }},"{{ r['msg'] | default('') }}" {% endfor %}
テンプレートの補足説明
- Playbook 中で 変数
results
として取得した複数のping結果を、1宛先ごとにループしています。 msg
は想定外のstete
の時のみ返ってくる値です。そのため、想定通りのstate
の場合にmsg
を出力しようとするとエラーになっていまいます。エラー対策として、default
フィルターを利用して、返ってこなかった場合に空文字になるようにしています。
■ 実行その1(全OK)
すべての宛先のping結果が想定通りの state
の場合です。
・playbookの実行
[vagrant@centos7 vagrant]$ ansible-playbook -i hosts ping.yml PLAY [ios] ********************************************************************* TASK [ping] ******************************************************************** ok: [10.0.0.1] => (item=192.168.1.1) ok: [10.0.0.1] => (item=192.168.1.2) ok: [10.0.0.1] => (item=192.168.1.3) ok: [10.0.0.1] => (item=192.168.1.4) ok: [10.0.0.1] => (item=192.168.1.5) ok: [10.0.0.1] => (item=192.168.1.6) ok: [10.0.0.1] => (item=192.168.1.7) ok: [10.0.0.1] => (item=192.168.1.8) ok: [10.0.0.1] => (item=192.168.1.9) ok: [10.0.0.1] => (item=192.168.1.10) TASK [output csv file] ********************************************************* changed: [10.0.0.1] PLAY RECAP ********************************************************************* 10.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
・CSV出力結果
[vagrant@centos7 vagrant]$ cat ping_from_10.0.0.1_result.csv "dest","packet_loss","packets_rx","packets_tx","rtt_avg","rtt_max","rtt_min","msg" "192.168.1.1","0%",5,5,2,9,1,"" "192.168.1.2","0%",5,5,2,9,1,"" "192.168.1.3","0%",5,5,8,9,8,"" "192.168.1.4","0%",5,5,7,9,1,"" "192.168.1.5","0%",5,5,6,9,1,"" "192.168.1.6","0%",5,5,8,9,8,"" "192.168.1.7","0%",5,5,8,9,8,"" "192.168.1.8","0%",5,5,7,9,1,"" "192.168.1.9","0%",5,5,7,9,1,"" "192.168.1.10","0%",5,5,8,9,8,""
■ 実行その2(一部NG)
一部宛先のping結果が想定外の state
の場合です。
・Playbook実行
[vagrant@centos7 vagrant]$ ansible-playbook -i hosts ping.yml PLAY [ios] ********************************************************************* TASK [ping] ******************************************************************** ok: [10.0.0.1] => (item=192.168.1.1) failed: [10.0.0.1] (item=192.168.1.2) => {"changed": false, "commands": ["ping 192.168.1.99 repeat 5"], "item": "192.168.1.99", "msg": "Ping failed unexpectedly", "packet_loss": "100%", "packets_rx": 0, "packets_tx": 5, "rtt": {"avg": null, "max": null, "min": null}} ok: [10.0.0.1] => (item=192.168.1.3) ok: [10.0.0.1] => (item=192.168.1.4) ok: [10.0.0.1] => (item=192.168.1.5) ok: [10.0.0.1] => (item=192.168.1.6) ok: [10.0.0.1] => (item=192.168.1.7) ok: [10.0.0.1] => (item=192.168.1.8) ok: [10.0.0.1] => (item=192.168.1.9) ok: [10.0.0.1] => (item=192.168.1.10) ...ignoring TASK [temp] ******************************************************************** changed: [10.0.0.1] PLAY RECAP ********************************************************************* 10.0.0.1 : ok=2 changed=1 unreachable=0 failed=0
想定外だった宛先に対するpingのタスクは failed
になります。
・CSV出力結果
以下の通り、疎通が取れる想定だった宛先に対して、ロス率100%だった場合は、msg
が Ping failed unexpectedly
となります。
[vagrant@centos7 vagrant]$ cat ping_from_10.0.0.1_result.csv "dest","packet_loss","packets_rx","packets_tx","rtt_avg","rtt_max","rtt_min","msg" "192.168.1.1","0%",5,5,2,9,1,"" "192.168.1.2",”100%",0,5,,,,"Ping failed unexpectedly" "192.168.1.3","0%",5,5,8,9,8,"" "192.168.1.4","0%",5,5,7,9,1,"" "192.168.1.5","0%",5,5,6,9,1,"" "192.168.1.6","0%",5,5,8,9,8,"" "192.168.1.7","0%",5,5,8,9,8,"" "192.168.1.8","0%",5,5,7,9,1,"" "192.168.1.9","0%",5,5,7,9,1,"" "192.168.1.10","0%",5,5,8,9,8,""
なお、疎通が取れない想定だった宛先に対して、ロス率100%未満 の場合は、msg
が Ping succeeded unexpectedly
となります。
■ まとめ
Ansible の ios_ping
モジュールと template
モジュール利用して、Cisco IOS からの ping 結果を CSV 出力してみました。
count
と timeout
の関係や、「何をもって成功/失敗とするか」あたりがポイントです。
また、今回はping実行ホスト1台につき1つのCSVファイルを生成しましたが、作り方次第では1つのファイルにまとめることも可能かと思います。
もし、今回のような内容をしたい場合に、本記事が参考になれば幸いです。