【Ansible】AnsibleでCisco機器を制御してみる(サンプルコード1 config収集編)


# 1. はじめに
※[前回](http://qiita.com/onifinger/items/4fdc70706dbbff595310)と同じです。
[こんなこと](https://www.ansible.com/press/red-hat-brings-devops-to-the-network-with-new-ansible-capabilities)とか[そんなこと](https://www.redhat.com/ja/about/press-releases/red-hat-brings-devops-network-new-ansible-capabilities)
というわけで、Ansibleのcoreのnetwork moduleが充実したみたいです。
＃ 取り上げるの遅いですよね…

http://docs.ansible.com/ansible/list_of_network_modules.html
Ios(Cisco), Eos(Arista), Junos(Juniper), はてはopen switchまで。

数千台のswitchを前に、expectかteraterm macroでウニウニやっていた
ぼくらには朗報、此れは使はずばいらいでかということで使ってみました。
使ったのは

+ ios_command.py
+ ios_config.py

の各モジュールです。

動作環境などは2016年3月時点の状況です。

# 2. 実行環境

|items|version|notes|
|---|---|---|
|mac OSX|10.10.x|母艦OS|
|Oracle Virtualbox|5.0.16 r105871|HV用途|
|CentOS|7.2|Ansible machine|
|Ansible|2.0.1.0|[ここ](http://releases.ansible.com/ansible-network/latest/)からげっと|
|Catalyst 3560E|IOS12.2|弄れるのがこれしかなかた|

### 構成
下記留意点のため、CentOS7上でAnsibleを動かしました。

# 3. 留意点
+ RedHat印のAnsibleでのみ動作可
    + mac OSXのbrew installで入るversionにはNW関連のupdateが含まれない(version 1.9.4)
    + yum installで入れるAnsibleにも同じくupdateが含まれない
        + ※2016年6月現在は含まれる
    + githubにはあるのでcloneしても可

# 4. Config収集するサンプルコード
```text:inventory_file
[cisco]
192.168.199.2
192.168.199.3

[cisco:vars]
ansible_ssh_user=operator
ansible_ssh_pass=operators_password
enable_pass=enable
```

```text:playbook_config_crawl.yml
---

- hosts: all
  gather_facts: no
  
  tasks:
   - name: crawl config file
     local_action:
       module: ios_command
       authorize: yes
       auth_pass: "{{ enable_pass }}"
       username: "{{ ansible_ssh_user }}"
       password: "{{ ansible_ssh_pass }}"
       host: "{{ inventory_hostname }}"
       commands:
         - show run
     register: result

   - name: log write out
     local_action: template src=/myfolder/conf.j2 dest=/myfolder/{{ inventory_hostname }}.log

   - name: parse config
     local_action: shell cat {{ inventory_hostname }}.log | sed -e 's/        \"//g' | sed -e 's/",//g' | sed -e "1,2d" | sed -e '$d' | sed -e '$d' > {{ inventory_hostname }}.conf

   - name: remove logfile
     local_action: file path=./{{ inventory_hostname }}.log state=absent
```

# 5. playbook解説
1. 基本的な組み立て
    手でやるなら以下です。

    ```
    $ enable
    Password:
    # show run
    ```

    terminalのloggingをオンにして、
    特権モードに移行して(term len 0とか要るかもしれんが)sh run叩いて
    configをfileに吐く、というやつです。
　　

2. crawl config file タスク
    local_action module内で、cisco moduleを呼びます。
    中身は以下の通り。

    ```python:playbook_detail
      local_action:
       module: ios_command                //使いたいモジュールを宣言
       authorize: yes                     //特権モードに移行する
       auth_pass: "{{ enable_pass }}"     //特権モードのパスワード
       username: "{{ ansible_ssh_user }}" //初回ログイン時ユーザ
       password: "{{ ansible_ssh_pass }}" //初回ログイン時ユーザのパスワード
       host: "{{ inventory_hostname }}"   //ループ用(複数台やっても大丈夫)
       commands:                          //ここから実際の発行コマンド
         - show run                       //config表示
     register: result                     //resultに表示結果を格納
    ```

    ちなみに、「configじゃなくてsh intとsh ip routeを採取したいんだよね！」
    などという2つのタスクを吐きたい欲張りさん向けには、
    同僚の書いている**[この記事](http://qiita.com/tbuchi888/items/2ff64060290bcabc721e)**のノウハウがオススメです。
　　

3. log write out タスク
    ansible実行マシンに中間fileを吐いています。
    conf.j2の中身は以下のようになっています。

    ```text:conf.j2
    {{ result.stdout_lines | to_nice_json }}
    ```
    前のタスクでresultに格納した内容をjson形式で表示し
    ホストのIPアドレス.logというファイルに書き出しています。
　　

4. parse config タスク
    json形式でfile生成したので、sedで無理矢理整形してリダイレクトしています。
    全然エレガントじゃないです。
    + jsonに入っている複数の半角スペースを消す
    + jsonに入っている「",」文字列を消す
    + １行目２行目を消す
    + 最終行の閉じ括弧を２回消す
    
　　
5. remove logfile タスク
　　中間ファイルの~.logを消してます。
  

# 6. コツ
local_action module内でnetwork moduleを使う、ということがコツだと思います。

Ansibleは、超シンプルにいうと
管理対象(操作対象といったほうが分かりが良いかもしれないが)のホストに対して
ssh接続して内部のpythonを操作してお仕事をするヒトです。

大半のNW機器にはpythonなんて入っていないので、
普通にAnsibleのplaybookを書くと上記の動きに当てはまらないことを想定すると、
local_actionで機器用のcommandを送りつける構図が思いつくと思います。

# 7. さらにつづく
肝心の実行方法を書き忘れていましたが、
サンプルコード一式を同じフォルダに入れて、以下です。

    ansible-playbook -i inventory_file playbook_config_crawl.yml

このサンプルコードをうまく使えば、複数台からのconfig採取が
コマンド１行で可能になります。

次は機器の設定変更をAnsibleからやるべく、ポートの設定変更のサンプルを示したいと思います。