たそ@ITインフラ初心者

taso@初心者エンジニア

新卒2年目 エンジニアが適当に語るブログてす

Ansibleでルータ設定 #3 設定出力編 part2

お疲れ様です。たそ(@taso_int)です。
来週初任給がもらえるのでワクワクしてます。
初任給で椅子を買いたいですね。
あと親にも何かあげたいです。 何かおススメありますかね。

今回も続きをやっていきたいと思います。
前回の内容について知りたい方はこちらへ

taso-int.hatenablog.com

前回の出来なかったところから行っていきます。

1.構成図

f:id:taso_int:20210523120754j:plain

以前の構成から192.168.1.2→192.168.1.254に変更します。
しかし、AnsiblleホストとSSH接続しており、playbookで変更すると
止まってしまうので手動で設定変更をします。
そこでstartup-configとrunnig-configの設定ファイルを保存して
変更部分を比較するplaybookを書きたいと思います。

2.動作設計

今回のplaybookの動作手順を考えたいと思います。
1.実際にコマンドをそれぞれ実行する。
2.実行結果をファイルで保存をする。 ←(ここまではできた)
3.ファイルを比較する。
4.比較結果をplaybook実行中に表示させる。
5.write memoryをするかを問い合わせる。

2番以降まで出来たので、3番以降を行っていきたいと思います。

3.手順

比較する方法でshellモジュールを使って直接diffするパターンと
diffモジュールをつかう方法があります。
(横地さん教えていただきありがとうございます。)

3-1.shellモジュールver
まずはshellを使って直接diffを行う方法から見てきます。

  tasks:
    - name: show startup
      ios_command:
        commands: show startup-config
      register: result

    - name: diff show 
      debug:
        var: result.stdout_lines

shellモジュールを使ってdiffをAnsiblleホストで直接実行するように指示を出してます。
(ルータ内ではない)
shellモジュールを利用するとなぜかエラー(赤文字)出力がされ
playbookが停止してしまいます。
これはコマンド結果のリターンコードが0以外になって、
shell モジュールがエラーと判定してしまっているとのことです。
この解決策をしてfailed_when:falseを設定することで
常に成功状態にさせる方法を取りました。

またfailed_when: result.rc not in [0, 1]と設定することで、
出力なしが0 出力ありが1 エラーが2と分類できるので、
本来のエラーを漏らさないようになるためこちらの方がいいと思います。

出力方法はdebugモジュールを利用し、var: result.stdout_linesを指定することで、
1行づつ出力されます。

3-2.diffモジュールver
diffモジュールを使用した場合です。
ansible.utils.fact_diff というモジュールを利用して行うことができます。
ただしansible 2.9 や ansible 2.10ではansible.utils というcollectionを
ansible-galaxy collection install ansible.utils でインストールする必要があります。

またshowコマンドで格納した変数を利用しているので、変数を分ける必要があります。
今回は変数を分けてcopyコマンドでファイル出力し、
その変数をdiffに再利用する形を取ります。
(jinja2 のうまい書き方がわからないのです)

  tasks:
    - name: show startup
      ios_command:
        commands: show startup-config | begin version
      register: result1

    - name: file make startupconf
      copy:
        content: "{{ result1.stdout[0] }}" 
        dest: "startconf_{{ inventory_hostname }}"

    - name: show running
      ios_command:
        commands: show running-config | begin version
      register: result2

    - name: file make runningconf
      copy:
        content: "{{ result2.stdout[0] }}" 
        dest: "runconf_{{ inventory_hostname }}"

    - name: diff
      ansible.utils.fact_diff:
        before: "{{ result1 }}"
        after: "{{ result2 }}"

こちらはdiffのモジュールなので出力も見やすく行ってくれます。

f:id:taso_int:20210523171515p:plain

やはり、shellやcommandモジュールは奥の手らしいですね。
(どうやって皆さんモジュール見つけてるんだろうか…)

3-3.保存方法
本来なら確認を取りたいのですが、分岐するのは難しいなと感じました。
そこで処理を一時的に停止させることのできるpauseモジュールがあるとのこと
(金魚の方本当に情報ありがとうございます。)
pauseで確認→OKならenter→そのままplaybookを実行
pauseで確認→NOならctrl+c→playbookを停止終了
pauseよりも上のtaskはconfigを保存してもしなくても行いたいのでこれでいいですね。
debugに入れて表示してもよかったですがnameにいれる荒技をしました。
こんな感じになりました。

    - name: running-configをstartup-configに保存します。 enterで実行 Ctrl+cで停止します
      pause: #enterで下のタスクが実行 ctrl+c後 aで下のタスクを実行せず停止

    - name: write memory
      ios_config:
        save_when: modified
      tags:
        - save

4.確認

最終的にはこのような感じになりました。
shell ver

---
- hosts: ios
  gather_facts: false

  tasks:
    - name: show startup
      ios_command:
        commands: show startup-config | begin version
      register: result

    - name: file make start
      template:
        src: ios_log.j2
        dest: "startconf_{{ inventory_hostname }}"

    - name: show running
      ios_command:
        commands: show running-config | begin version
      register: result

    - name: file make run
      template:
        src: ios_log.j2
        dest: "runconf_{{ inventory_hostname }}"

    - name: diff
      shell: diff -u startconf_{{ inventory_hostname }} runconf_{{ inventory_hostname }}
      register: result
      failed_when: false
      
    - name: diff show 
      debug:
        var: result.stdout_lines

    - name: running-configをstartup-configに保存します。 enterで実行 Ctrl+cで停止します
      pause:
        
    - name: write memory
      ios_config:
        save_when: modified
      tags:
        - save

diff ver

---
- hosts: ios
  gather_facts: false

  tasks:
    - name: show startup
      ios_command:
        commands: show startup-config | begin version
      register: result1

    - name: file make startupconf
      copy:
        content: "{{ result1.stdout[0] }}" 
        dest: "startconf_{{ inventory_hostname }}"

    - name: show running
      ios_command:
        commands: show running-config | begin version
      register: result2

    - name: file make runningconf
      copy:
        content: "{{ result2.stdout[0] }}" 
        dest: "runconf_{{ inventory_hostname }}"

    - name: running-configをstartup-configに保存します。 enterで実行 Ctrl+cで停止します
      pause:

    - name: diff
      ansible.utils.fact_diff:
        before: "{{ result1 }}"
        after: "{{ result2 }}"

設定変更後、試しにshellバージョンでそのまま実行してみます。

f:id:taso_int:20210523222929p:plain

いい感じに出来てます。

ちなみにpauseで停止させるとこんな感じに

f:id:taso_int:20210523223013p:plain

いいですね

以上で完成になります。やったね!

来週は基本情報勉強のためお休みします。
ここまで読んでいただきありがとうございました。