てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] 「つまずき Ansible 【Part27】ネットワーク機器の状態確認をしたい」ふりかえり

はじめに

2021/01/23 に、YouTube Live で「つまずき Ansible 【Part27】ネットワーク機器の状態確認をしたい」という配信をしました。

実際に作業しながら(ときには)エラーと戦って進めるシリーズです。

今回は、以下の記事を参照しながら、ネットワーク機器の状態確認する処理を試しました。

www.ansible.com

tekunabe.connpass.com

  • 環境
    • Ansible 2.10.5
      • (配信中、記事の前提のバージョンが不明と言ってしまいましたが、実際は 2.9.15 と記載がありました。失礼しました。)


動画

youtu.be

  • 00:00 イントロダクション
  • 05:56 情報の取得とパース結果の表示
  • 21:55 インターフェース状態のバリデーション
  • 30:26 復旧
  • 32:46 BGP状態のバリデーション
  • 44:49 おわりに

■ やったこと

venv の作成と ansible 2.10.5 のインストール

まず、環境の準備として、新しい venv に ansible をインストール。

[admin@gitlab ~]$ python3 -m venv envs/a210
[admin@gitlab ~]$ source envs/a210/bin/activate
(a210) [admin@gitlab ~]$ pip install ansible
(略)
(a210) [admin@gitlab ~]$ ansible --version
ansible 2.10.5
(略)

表示用Playbook の実行

Playbook (公式ブログからの引用)を実行

---
- hosts: nxos
  connection: ansible.netcommon.network_cli
  gather_facts: false
  vars:
    ansible_network_os: cisco.nxos.nxos
    ansible_user: "changeme"
    ansible_password: "changeme"

  tasks:
  - name: "Fetch interface state and parse with pyats"
    ansible.utils.cli_parse:
      command: show interface
      parser:
        name: ansible.netcommon.pyats
    register: nxos_pyats_show_interface

  - name: print structured interface state data
    ansible.builtin.debug:
      msg: "{{ nxos_pyats_show_interface['parsed'] }}"

ansible.utils.cli_parse モジュール関連のエラー

ansible.utils.cli_parse モジュールが見つからないエラー。

ERROR! couldn't resolve module/action 'ansible.utils.cli_parse'. This often indicates a misspelling, missing collection, or incorrect module path.

上記エラーの対策として、ansible.utils collection をインストール。

(a210) [admin@gitlab stumble]$ ansible-galaxy collection install ansible.utils
Starting galaxy collection install process
Process install dependency map
Starting collection install process
Installing 'ansible.utils:1.0.1' to '/home/admin/.ansible/collections/ansible_collections/ansible/utils'
Downloading https://galaxy.ansible.com/download/ansible-utils-1.0.1.tar.gz to /home/admin/.ansible/tmp/ansible-local-23876jjourm5u/tmppi521mhv
ansible.utils (1.0.1) was installed successfully

paramiko 関連のエラー

再度 Playbook 実行で、paramiko が見つからないエラー。

TASK [Fetch interface state and parse with pyats] *****************************************************************************
fatal: [nxos01]: FAILED! => {"changed": false, "msg": ["paramiko is not installed: No module named 'paramiko'"]}

上記エラーの対策として、paramiko をインストール。

pip install paramiko

pyats 関連のエラー

再度 Playbook 実行で、pyats が見つからないエラー。

TASK [Fetch interface state and parse with pyats] *****************************************************************************
fatal: [nxos01]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (genie) on gitlab's Python /home/admin/envs/a210/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter Failed to import the required Python library (pyats) on gitlab's Python /home/admin/envs/a210/bin/python3. Please read the module documentation and install it in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"}

上記エラーの対策として、pyats をインストール。

pip install pyats

gccのエラー

    gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/home/admin/envs/a210/include -I/usr/include/python3.6m -c multidict/_multidict.c -o build/temp.linux-x86_64-3.6/multidict/_multidict.o -O2 -std=c99 -Wall -Wsign-compare -Wconversion -fno-strict-aliasing -pedantic
    unable to execute 'gcc': No such file or directory
    error: command 'gcc' failed with exit status 1
    
    ----------------------------------------
Command "/home/admin/envs/a210/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-ptsvl0o2/multidict/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-eplnwr3p-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/admin/envs/a210/include/site/python3.6/multidict" failed with error code 1 in /tmp/pip-build-ptsvl0o2/multidict/
You are using pip version 9.0.3, however version 20.3.3 is available.

上記の対策として、yum でインストール。(実際はもっと最小限にできたと思います)

yum groupinstall "Development Tools"
sudo yum install python3-* -y

その後 pip install "pyats[full]" 実行で無事インストール。

再度 Playbook 実行。無事に show interface 実行結果がパースされて表示される。

(a210) [admin@gitlab stumble]$ ansible-playbook -i inventory.ini debug.yml 

PLAY [nxos] *******************************************************************************************************************

TASK [Fetch interface state and parse with pyats] *****************************************************************************
ok: [nxos01]

TASK [print structured interface state data] **********************************************************************************
ok: [nxos01] => {
    "msg": {
        "Ethernet2/1": {
            "admin_state": "up",
            "auto_mdix": "off",
            "auto_negotiate": false,
            "bandwidth": 1000000,
            "beacon": "off",
            "counters": {
                "in_bad_etype_drop": 0,
                "in_broadcast_pkts": 0,
                "in_crc_errors": 0,
                "in_discard": 0,
                "in_errors": 0,
                "in_if_down_drop": 0,
                "in_ignored": 0,
                "in_jumbo_packets": 0,
                "in_mac_pause_frames": 0,
                "in_multicast_pkts": 0,
                "in_no_buffer": 0,
                "in_octets": 0,
                "in_overrun": 0,
                "in_oversize_frame": 0,
                "in_pkts": 0,
                "in_runts": 0,
                "in_short_frame": 0,
                "in_storm_suppression_packets": 0,
                "in_underrun": 0,
                "in_unicast_pkts": 0,
                "in_unknown_protos": 0,
                "in_watchdog": 0,
                "in_with_dribble": 0,
                "last_clear": "never",
                "out_babble": 0,
                "out_broadcast_pkts": 0,
                "out_collision": 0,
                "out_deferred": 0,
                "out_discard": 0,
                "out_errors": 0,
                "out_jumbo_packets": 0,
                "out_late_collision": 0,
                "out_lost_carrier": 0,
                "out_mac_pause_frames": 0,
                "out_multicast_pkts": 0,
                "out_no_carrier": 0,
                "out_octets": 0,
                "out_pkts": 0,
                "out_unicast_pkts": 0,
                "rate": {
                    "in_rate": 0,
                    "in_rate_bps": 0,
                    "in_rate_pkts": 0,
                    "in_rate_pps": 0,
                    "load_interval": 0,
                    "out_rate": 0,
                    "out_rate_bps": 0,
                    "out_rate_pkts": 0,
                    "out_rate_pps": 0
                },
                "rx": true,
                "tx": true
            },
            "dedicated_interface": true,
            "delay": 10,
            "duplex_mode": "full",
            "efficient_ethernet": "n/a",
            "enabled": true,
            "encapsulations": {
                "encapsulation": "arpa"
            },
            "ethertype": "0x8100",
            "flow_control": {
                "receive": false,
                "send": false
            },
            "interface_reset": 1,
            "last_link_flapped": "02:25:36",
            "link_state": "up",
            "mac_address": "0000.0000.002f",
            "medium": "broadcast",
            "mtu": 1500,
            "oper_status": "up",
            "phys_address": "5254.0003.xxxx",
            "port_channel": {
                "port_channel_member": false
            },
            "port_mode": "routed",
            "port_speed": "1000",
            "reliability": "255/255",
            "rxload": "1/255",
            "switchport_monitor": "off",
            "txload": "1/255",
            "types": "Ethernet"
        },
        "Ethernet2/10": {
            "admin_state": "down",
...(略)...

バリデーション用Playbook の実行以降

Validation 以降 については動画をご参照下さい。

(チャプター再掲)

  • 00:00 イントロダクション
  • 05:56 情報の取得とパース結果の表示
  • 21:55 インターフェース状態のバリデーション
  • 30:26 復旧
  • 32:46 BGP状態のバリデーション
  • 44:49 おわりに


おわりに

配信中はかなり雰囲気で試しましたが、使いこなすには、JSON Schema の書き方や、データの構造をよく理解したほうが良いと思いました。


Part28 にむけて

以下のネタを検討中です。気が向いたものをやります。

  • Ansible 2.10 関連
  • connection: local ななにか
  • Jinja2、フィルター
  • Windows
  • ESXi で VM作成