これは Ansible Advent Calendar 2017 の18日目の記事です。
■ やりたいこと
Ansible で Cisco IOS から複数のIPアドレスに対してpingを実行し、その結果をCSVファイルに出力します。本記事では、利用する ios_ping
モジュールの説明と、 Playbookのサンプルをご紹介します。
ios_ping
はCisco IOS の機器から ping を実行して、ロス率やRTT値など パース して返してくれるモジュールです。Ansible 2.4 で追加されました。(本記事は Ansible 2.4.2 を前提としています)
参考: ios_ping モジュール公式ドキュメント
手作業によるコマンド結果と、パースして取得できる情報の関係は以下の通りです。
主なオプション
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
gather_facts: no
connection: local
tasks:
- name: ping
ios_ping:
dest: "{{ item }}"
count: 5
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
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
[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
になります。
以下の通り、疎通が取れる想定だった宛先に対して、ロス率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つのファイルにまとめることも可能かと思います。
もし、今回のような内容をしたい場合に、本記事が参考になれば幸いです。