てくなべ

インフラ、ネットワーク、自動化などの技術的なことを書いていきます。

ネットワーク機器のコマンド結果をパースする parse_cli_textfsm フィルタープラグインを試す (Ansible 2.4新機能)

f:id:akira6592:20170923214714p:plain

Ansible 2.4 で Ansible でネットワーク機器のコマンド結果をパースするための parse_cli_textfsm というフィルタープラグインが搭載されました。

http://docs.ansible.com/ansible/latest/playbooks_filters.html#network-cli-filters

今回は簡単な例で試してみることのします。

■ 1. 仕組み

parse_cli_textfsm は、テンプレートに従ってコマンド結果をパースする TextFSM というライブラリを呼び出します。 そのため、別途テンプレートファイルを用意する必要があります。

ありがたいことに、networktocodeのリポジトリにisoの show ip ospf neighbor や、junos show interfaces 等に対応した計180近い(2017/09/23現在)テンプレートファイルがあります。 今回はこれらを利用させていただきます。

github.com

■ 2. 環境の準備

TextFSM のインストール

前述したように、 parse_cli_textfsm フィルタープラグインでは、内部で TextFSM を利用しているので、あらかじめインストールします。

sudo pip install textfsm

テンプレートファイルのダウンロード

Network to Code のリポジトリからテンプレートファイル一式をダウンロードします。 ひとまず、playbookを作成する予定のディレクトリで git clone します。

git clone https://github.com/networktocode/ntc-templates.git

もちろん、利用したいテンプレートファイルが決まっているなら個別にダウンロードしてもOKです。

■ 3. Playbook の準備

---
- hosts: ios
  gather_facts: no
  connection: local

  tasks:
    - name: show int status
      ios_command:
        commands:
          - show int status
        provider: "{{ cli }}"
      register: result

    - name: DEBUG
      debug:
        msg: "{{ result.stdout[0] | parse_cli_textfsm('./ntc-templates/templates/cisco_ios_show_interfaces_status.template') }}"

  vars:
    cli: 
      host: "{{ inventory_hostname }}" 
      username: "{{ ansible_user }}"
      password: "{{ ansible_password }}"
      authorize: true
      auth_pass: "{{ cisco_enable_secret }}"

■ 4. 実行

先ほど作成した playbook を実行します。

[vagrant@centos7 vagrant]$ ansible-playbook ios_parse.yml

PLAY [ios] ************************************************************************************************************************************************************************************

TASK [show int status] ****************************************************************************************************************************************************************************
ok: [192.168.1.254]

TASK [DEBUG] **********************************************************************************************************************************************************************************
ok: [192.168.1.254] => {
    "msg": [
        {
            "DUPLEX": "auto",
            "NAME": "",
            "PORT": "Gi1/0/1",
            "SPEED": "auto",
            "STATUS": "notconnect",
            "TYPE": "10/100/1000BaseTX",
            "VLAN": "1"
        },
        {
            "DUPLEX": "auto",
            "NAME": "",
            "PORT": "Gi1/0/2",
            "SPEED": "auto",
            "STATUS": "notconnect",
            "TYPE": "10/100/1000BaseTX",
            "VLAN": "1"
        },
        ~(略)~
        {
            "DUPLEX": "a-full",
            "NAME": "management",
            "PORT": "Gi1/0/24",
            "SPEED": "a-1000",
            "STATUS": "connected",
            "TYPE": "10/100/1000BaseTX",
            "VLAN": "192"
        }
    ]
}

PLAY RECAP ************************************************************************************************************************************************************************************
192.168.1.254               : ok=2    changed=0    unreachable=0    failed=0

無事に show int status の結果がパースされました。

■ 5. まとめ

ネットワーク機器のshowコマンドの結果は、人が目視する分には問題ないのですが、特定の値をプログラムに判断させるといったことが難しいです。 このようにパースする仕組みを利用すると、 assert モジュールなど併用して「Gi1/0/10 の VLAN が 99 であれば正常とする」といった簡単なテストもしやすくなるのではないでしょうか。