はじめに
2020/08/22 に、YouTube Live で「つまずき Ansible 【Part14】ネットワーク機器のshowコマンドログ収集」という配信をしました。
実際に作業しながらエラーと戦って進めるシリーズです。
今回は、Cisco のネットワーク機器に対して show コマンドを実行し、手作業風のログを生成する Playbook と Jinja2 テンプレートを作成しました。
やったことや、わかったことをふりかえります。
動画
■ やったこと
ひとまず コマンド実行結果を画面に表示する
Playbook
--- - hosts: ios gather_facts: false vars: commands: - show ip interface brief - show ip route tasks: - name: show command ios_command: commands: "{{ commands }}" register: result # uketoru - name: debug debug: var: result.stdout
ついでに、結果を yaml 形式で表示にするように変更
参考: [Ansible] callback plugin を yaml に変更して標準出力の改行を見やすくする - てくなべ (tekunabe)
export ANSIBLE_STDOUT_CALLBACK=yaml
結果
% ansible-playbook -i inventory.ini ios_log.yml TASK [debug] ********************************************************************************************************************************************************************** ok: [rt02] => result.stdout: - |- Interface IP-Address OK? Method Status Protocol GigabitEthernet0/0 192.168.1.12 YES TFTP up up GigabitEthernet0/1 unassigned YES TFTP administratively down down GigabitEthernet0/2 unassigned YES TFTP administratively down down GigabitEthernet0/3 10.0.0.2 YES TFTP up up Loopback0 10.255.255.2 YES TFTP up up - |- Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP ...(略)... Gateway of last resort is 192.168.1.1 to network 0.0.0.0 S* 0.0.0.0/0 [1/0] via 192.168.1.1 10.0.0.0/8 is variably subnetted, 4 subnets, 2 masks C 10.0.0.0/24 is directly connected, GigabitEthernet0/3 L 10.0.0.2/32 is directly connected, GigabitEthernet0/3 O 10.255.255.1/32 [110/2] via 10.0.0.1, 4w1d, GigabitEthernet0/3 C 10.255.255.2/32 is directly connected, Loopback0 192.168.1.0/24 is variably subnetted, 2 subnets, 2 masks C 192.168.1.0/24 is directly connected, GigabitEthernet0/0 L 192.168.1.12/32 is directly connected, GigabitEthernet0/0
ファイルに書き出す
Playbook
--- - hosts: ios gather_facts: false vars: commands: - show ip interface brief - show ip route tasks: - name: show command ios_command: commands: "{{ commands }}" register: result # uketoru - name: file template: src: ios_log.j2 dest: "ios_log_{{ inventory_hostname }}"
テンプレートファイル ios_log.j2
{% for cmd in commands %} {{ inventory_hostname }}# {{ cmd }} {{ result.stdout[loop.index0] }} {% endfor %}
上記では、コマンド名を定義して commands
で繰り返していますが、result.stdout
でも構いません。
result.stdout
の場合は以下の通り。
{% for out in result.stdout %} {{ inventory_hostname }}# {{ commands[loop.index0] }} {{ out }} {% endfor %}
結果
- Playbook 実行ログ
% ansible-playbook -i inventory.ini ios_log.yml PLAY [ios] ******************************************************************************************************** TASK [show command] *********************************************************************************************** ok: [rt01] ok: [rt02] TASK [file] ******************************************************************************************************* changed: [rt01] changed: [rt02] PLAY RECAP ******************************************************************************************************** rt01 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 rt02 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 生成されたファイル
ios_log_rt01
rt01# show ip interface brief Interface IP-Address OK? Method Status Protocol GigabitEthernet0/0 192.168.1.11 YES TFTP up up GigabitEthernet0/1 unassigned YES TFTP administratively down down GigabitEthernet0/2 unassigned YES TFTP administratively down down GigabitEthernet0/3 10.0.0.1 YES TFTP up up Loopback0 10.255.255.1 YES TFTP up up rt01# show ip route Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP ...(略)... Gateway of last resort is not set 10.0.0.0/8 is variably subnetted, 4 subnets, 2 masks C 10.0.0.0/24 is directly connected, GigabitEthernet0/3 L 10.0.0.1/32 is directly connected, GigabitEthernet0/3 C 10.255.255.1/32 is directly connected, Loopback0 O 10.255.255.2/32 [110/2] via 10.0.0.2, 4w1d, GigabitEthernet0/3 192.168.1.0/24 is variably subnetted, 2 subnets, 2 masks C 192.168.1.0/24 is directly connected, GigabitEthernet0/0 L 192.168.1.11/32 is directly connected, GigabitEthernet0/0
ios_log_rt02
rt02# show ip interface brief Interface IP-Address OK? Method Status Protocol GigabitEthernet0/0 192.168.1.12 YES TFTP up up GigabitEthernet0/1 unassigned YES TFTP administratively down down GigabitEthernet0/2 unassigned YES TFTP administratively down down GigabitEthernet0/3 10.0.0.2 YES TFTP up up Loopback0 10.255.255.2 YES TFTP up up rt02# show ip route Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP ...(略)... Gateway of last resort is 192.168.1.1 to network 0.0.0.0 S* 0.0.0.0/0 [1/0] via 192.168.1.1 10.0.0.0/8 is variably subnetted, 4 subnets, 2 masks C 10.0.0.0/24 is directly connected, GigabitEthernet0/3 L 10.0.0.2/32 is directly connected, GigabitEthernet0/3 O 10.255.255.1/32 [110/2] via 10.0.0.1, 4w1d, GigabitEthernet0/3 C 10.255.255.2/32 is directly connected, Loopback0 192.168.1.0/24 is variably subnetted, 2 subnets, 2 masks C 192.168.1.0/24 is directly connected, GigabitEthernet0/0 L 192.168.1.12/32 is directly connected, GigabitEthernet0/0
テンプレートファイルをカスタマイズすることでいろいろ応用できます。
例えば、now
で現在時刻を表示。
{{ now(False, '%Y%m%d_%H%M%S') }}
ただし、実際のコマンド実行時刻ではなく、ログファイル生成時なので注意。(ご指摘ありがとうございます!)
now()だと、j2生成時の時間になるので、コマンド実行時とはちょっとズレるのかな?#tekunabe
— z a k i (@zaki_hmkc) 2020年8月22日
Part15 にむけて
以下のネタを検討中です。気が向いたものをやります。
- connection: local ななにか
- Ansible Toewr / AWX をコマンドがら操作する
- ansible.cfg
- Jinja2、フィルター
- Windows
- when、assert など