【telnetでHŞRPプライオリティ変更】

---telnetモジュールでNW自動化の設定---

Ansibleの特徴の一つに「エージェントレスである」と言われる。。
他の自動化ツール、例えばChefやPuppetと比べて、設定対象側にエージェントソフトをインストールする必要がなく
SSHで接続する条件さえ満たせば他に追加の設定は無い、ということらしい。
しかしすぐにはsshを有効にできないとか、もともと管理対象側にsshの機能がないという環境は現状まだあると思う。特にNWインフラ系。
今回は、sshが使えない場合の暫定的な対応を想定して、Ansibleのtelnetモジュールを使ってCisco機の工事手順の一部を作成してみた。

<<HSRPプライオリティ変更>>

  • 例として以下のエクセルの手順書の工事を自動化することを想定

*1

f:id:pinn38:20190504203841p:plain

telnetでHSRPプライオリティ変更

telnetモジュールを使ってこの工事手順を自動化するために作ったplaybookと実行シーケンス

f:id:pinn38:20190503155602p:plain

telnetでHSRPプライオリティ変更用yml

 

f:id:pinn38:20190503160111p:plain

telnetでHSRPプライオリティ変更シーケンス

playbookを4回実行してやっと完了する手順になった。
切戻工程はパラメータを少し変えて使いまわせる。が、実行順序の確認や編集のための手間が多く、煩雑。

実行順序はjenkinsやAnsibleTowerなどのトリガー機能で連動させるかな。

以下にA、B、DのplaybookとF,Gのインべントリーファイルを記載。

 


<<Playbook.A>>

cisco_telnet_chk.yml

---
- hosts: cisco
  connection: local
  gather_facts: False
  tasks:
    - name: pre check
      telnet:
        user: "{{user}}"
        password: "{{pass}}"
        login_prompt: "Username: "
        prompts:
          - "[>|#]|Password: "
        command:
          - terminal length 0
          - enable
          - "{{enpass}}"
          - "show standby Vlan{{vlan}}"
          - "show run interface Vlan{{vlan}}"
      changed_when: False
      register: command_result_pre
      failed_when: '"State is Standby" in "command_result_pre"'
    - name: pre debug
      debug:
        var: command_result_pre.output

    - name: pre log export
      local_action:
        module: copy
        dest: "{{log_dir}}/{{inventory_hostname}}.log"
        backup: yes
        content: "{{ command_result_pre.output}}"
      changed_when: False

<<inventory.F>>

telnetcisco

[cisco]
ciscoR1 ansible_host=192.168.3.215 vlan="951" hsrp_grnum="6"
#ciscoR3 ansible_host=192.168.3.3 vlan="952" hsrp_grnum="7"
#ciscoR5 ansible_host=192.168.3.19 vlan="953" hsrp_grnum="8"
#ciscoR7 ansible_host=192.168.3.35 vlan="954" hsrp_grnum="9"

[cisco:vars]
user="hoge"
pass="1234"
enpass="1234"
log_dir="/home/ktn/telnetlog"
ansible_become=yes    
ansible_become_method=enable    
#hsrp_pri="80"     
hsrp_pri="120"     

 

<<Playbook.B>>

cent_hsrp_actchk.yml

---
- hosts: localhost
  gather_facts: no
  connection: local
  tasks:
     - name: check status  
       shell:     "cat /home/ktn/telnetlog/{{hostfile}}.log"
       register:    check_status
       failed_when: "'item ' not in check_status.stdout"
       with_items:
         - "Active router is local"
         - "standby {{hsrp_grnum}} priority {{act_pri}}"
         - "Standby router is {{peeradd}}"
       changed_when: False

<<inventory.G>>

telnetcent

[cent]
localhost  ansible_host=192.168.3.218
[cent:vars]
ansible_ssh_user=hoge
ansible_ssh_pass=1234
ansible_port=22

hostfile="ciscoR1"
vlan="951" 
hsrp_grnum="6" 
act_pri="120" 
sby_pri="80" 
peeradd="10.100.14.194"
log_dir="/home/ktn/telnetlog"

 

<<Playbook.D>>

cisco_telnet_ACTconf.yml

---
- hosts: cisco
  connection: local
  gather_facts: False
  tasks:
    - name: configuer telnet
      telnet:
        user: "{{user}}"
        password: "{{pass}}"
        login_prompt: "Username: "
        prompts:
          - "[>|#]|Password: "
        command:
          - terminal length 0
          - enable
          - "{{enpass}}"
          - "conf t"
          - "int Vlan{{vlan}}"
          - "standby {{hsrp_grnum}} priority 120"
      changed_when: False
      register: command_result

    - name: configurer debug
      debug:
        var: command_result.output

    - name: pause
      pause:
        seconds: 15

    - name: after telnet
      telnet:
        user: "{{user}}"
        password: "{{pass}}"
        login_prompt: "Username: "
        prompts:
          - "[>|#]|Password: "
        command:
          - terminal length 0
          - enable
          - "{{enpass}}"
          - "show standby Vlan{{vlan}}"
          - "show run interface Vlan{{vlan}}"
      changed_when: False
      register: command_result_after

    - name: debug_after
      debug:
        var: command_result_after.output

    - name: log export_after
      local_action:
        module: copy
        dest: "{{log_dir}}/{{inventory_hostname}}.log"
        backup: yes
        content: "{{ command_result_after.output}}"
      changed_when: False

<<確認>>

  • 特権モードに移行しcisco機器への設定が可能なこと
  • telnetモジュールで冪等性の担保ができるか
  • telnet接続とssh接続で利用できるモジュール機能の違いをいくつか実装してみて確認する。実行ログが指定のディレクトリに出力されるかどうかpauseが使えるかwait_forwhenが使えるか/等


<<結果と課題>>

  • telnetモジュールでは、commandで実際のコマンドをリストで記載しvtyで投入していくだけの動作となり冪等性は担保されない。変更前確認⇒変更⇒変更後確認の都度に確認するための仕組みが必要。
  • sshでは利用できていた多くのサブモジュールが機能しない。例えば、コマンド出力の応答文字列をwait_forwhenを使ってyamlで条件判断させたかったが認識しなかった。
  • hsrpのpreempt delayを待つためにpauseを入る場合、telnetモジュール対してグローバルにpause指定できるが、コマンド毎には指定できない。

<<現状の暫定対応>>

  • 変更前確認コマンド投入⇒ファイル比較⇒変更コマンド投入⇒変更前確認コマンド投入⇒ファイル比較、、、という風にplaybookをに分けて、確認工程はlocal_actionモジュールでファイルをコントローラに保存し、コントローラ側のcommandshellモジュールを使って比較する方法で対応することにした。

<<思ったこと>>

  • telnetモジュールでは使える機能がかなり限定されるため、自動化手順の実装の工程が多く複雑になる。telnetモジュールを無理やり使うくらいならこれま通りteratermマクロとシェルスクリプトでいいやっと思った。公式ドキュメントでもtelnetモジュールは主にsshを有効にするための手段として使われる、、、とあるように、可能な限りSSHを有効化にシフトして行くのが良い。次回は、ssh有効化するためのtelnetモジュールを作成し、sshを使う方式を恒久対応とする予定。

 

 

 

 

*1:パラメータはすべてサンプル値です