てくなべ

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

Ansible の ios_facts モジュールでCisco IOS 機器のシステム情報やインターフェース情報を取得する

f:id:akira6592:20170527151631p:plain

■ はじめに

Ansible には 2.2 から Cisco IOS の システム情報やインターフェース情報などを収集する ios_facts というモジュールが追加されています。 どのような結果になるのか確認するために試してみます。

[公式ドキュメント]

 ios_facts - Collect facts from remote devices running Cisco IOS — Ansible Documentation

[参考情報]

 AnsibleでCisco IOSの情報収集 - ios_facts - Qiita

なお、ところどころでモジュールのコードを確認していますが、今回は Ansible 2.3 の ios_facts.py を確認しています。

ansible/ios_facts.py at stable-2.3 · ansible/ansible · GitHub

この ios_facts という標準モジュールではなく、NAPALMと連携するモジュールを利用する場合は、以下の記事をご参照ください。

tekunabe.hatenablog.jp


■ 情報収集の対象範囲の指定について(gather_subset オプション)

gather_subset というオプションで情報収集する対象を指定できます。 デフォルトでは !config となっており、コンフィグが除外がされる形となります。

ドキュメントには、ほかのどのような指定ができるか記載されていませんが、モジュールのコードを読むと以下のオプションが指定できることが分かります。

  • all
  • config
  • hardware
  • interfaces

どの指定でどの情報が取得できるかは公式ドキュメントの「Return Values」に記載されています。

ios_facts - Collect facts from remote devices running Cisco IOS — Ansible Documentation


■ 全情報取得

今回は、gather_subset: all という指定をして全情報を取得してみます。

Playbook

以下のようなplaybook を作成します。ansible.cfg は特に作成していません。

- hosts: cisco          # インベントリファイルに定義済み
  gather_facts: no
  connection: local

  tasks:
    - name: facts
      ios_facts:
        gather_subset: all
        provider: "{{ cli }}"
      register: result
    - name: debug
      debug:
        msg: "{{ result }}"

  vars:
    cli: # 認証情報。各変数はインベントリファイルに定義済み
      host:     "{{ inventory_hostname }}"    # ホスト対象ホスト
      username: "{{ ansible_user }}"          # ログインユーザー
      password: "{{ ansible_password }}"      # ログインパスワード

実行結果

実行して結果を確認してみます。

[root@sv01 ansible]# ansible-playbook cf.yml

PLAY [cisco] **********************************************************************************************************************************

TASK [facts] **********************************************************************************************************************************
ok: [x.x.x.x]

TASK [debug] **********************************************************************************************************************************
ok: [x.x.x.x] => {
    "changed": false, 
    "msg": {
        "ansible_facts": {
"ansible_net_all_ipv4_addresses": [
    "10.0.0.51"
], 
            "ansible_net_all_ipv6_addresses": [], 
            "ansible_net_config": "Building configuration...\n\nCurrent configuration : 3940 bytes\n!\n! Last configuration change at 02:03:09 UTC Sat May 27 2017\n!\nversion 16.3\nservice timestamps debug datetime msec(略)\nend", 
"ansible_net_filesystems": [
    "bootflash:"
], 
"ansible_net_gather_subset": [
    "hardware", 
    "default", 
    "interfaces", 
    "config"
], 
            "ansible_net_hostname": "csr1", 
            "ansible_net_image": "bootflash:packages.conf", 
"ansible_net_interfaces": {
    "GigabitEthernet1": {
        "bandwidth": 1000000, 
        "description": null, 
        "duplex": "Full", 
        "ipv4": {
            "address": "10.0.0.51", 
            "masklen": 24
        }, 
        "lineprotocol": "up ", 
        "macaddress": "2cc2.60xx.xxxx", 
        "mediatype": "RJ45", 
        "mtu": 1500, 
        "operstatus": "up", 
        "type": "CSR vNIC"
    }, 
                "GigabitEthernet2": {
                    "bandwidth": 1000000, 
                    "description": null, 
                    "duplex": "Full", 
                    "ipv4": null, 
                    "lineprotocol": "up ", 
                    "macaddress": "2cc2.60xx.xxxx", 
                    "mediatype": "RJ45", 
                    "mtu": 1500, 
                    "operstatus": "up", 
                    "type": "CSR vNIC"
                }, 
                "GigabitEthernet3": {
                    "bandwidth": 1000000, 
                    "description": null, 
                    "duplex": "Full", 
                    "ipv4": null, 
                    "lineprotocol": "up ", 
                    "macaddress": "2cc2.60xx.xxxx", 
                    "mediatype": "RJ45", 
                    "mtu": 1500, 
                    "operstatus": "up", 
                    "type": "CSR vNIC"
                }, 
                "GigabitEthernet4": {
                    "bandwidth": 1000000, 
                    "description": null, 
                    "duplex": "Full", 
                    "ipv4": null, 
                    "lineprotocol": "up ", 
                    "macaddress": "2cc2.60xx.xxxx", 
                    "mediatype": "RJ45", 
                    "mtu": 1500, 
                    "operstatus": "up", 
                    "type": "CSR vNIC"
                }
            }, 
            "ansible_net_memfree_mb": 1723809, 
            "ansible_net_memtotal_mb": 2047264, 
            "ansible_net_model": null, 
"ansible_net_neighbors": {
    "null": [
        {
            "host": null, 
            "port": null
        }
    ]
}, 
            "ansible_net_serialnum": "9KXI0DXXXXX", 
            "ansible_net_version": "16.3.1"
        }, 
        "changed": false
    }
}

PLAY RECAP ************************************************************************************************************************************
x.x.x.x              : ok=2    changed=0    unreachable=0    failed=0  

■ 実行されるshowコマンド

実行結果の雰囲気からおおよそ分かりますが、どのようなshowコマンドが実行されるのか、念のためコードを確認しました。以下のコマンドが仕込まれていました。

  • dir
  • show memory statistics
  • show version
  • show running-config
  • show interfaces
  • show ipv6 interface
  • show lldp
  • show lldp neighbors detail

■ さいごに

稼働中のネットワーク機器の情報を収集したいケースは割とよくあると思いますが、自作しなくてもここまでできますので、もし、取得したい情報がこのモジュールで取得できるのであれば、利用してみるのもよいのではないでしょうか。

なお、Ansible を利用せずに、pythonスクリプト中でなるべくパース処理の手間を省きたい場合は、TextFSMというライブラリと ntc-template というテンプレート集を利用するのが良いと思います。 github.com github.com