Cisco DNA CenterをAnsibleから操作する(自作モジュール編)


はじめに

以下の記事に続き、サードパーティモジュールをベースに、モジュールを自作してみました。

Cisco DNA CenterをAnsibleから操作する(uriモジュール編)
Cisco DNA CenterをAnsibleから操作する(サードパーティモジュール編)

モジュール概要

AnsibleからDNA CenterへHTTPS GETを行う汎用的なモジュールdnac_getを作成します。以下の通り、取得する情報毎にURLの末尾が異なるため、v1より右側のパスをオプションurl_pathで指定できるようにします。

例1)デバイス一覧の取得
https://sandboxdnac2.cisco.com/api/v1/network-device

例2)特定のIPアドレスを持つデバイス情報の取得
https://sandboxdnac2.cisco.com/api/v1/network-device/ip-address/IPアドレス

例3)デバイス台数の取得
https://sandboxdnac2.cisco.com/api/v1/network-device/count

例4)全機器のインターフェースカウントの取得
https://sandboxdnac2.cisco.com/api/v1/interface/count

自作モジュール

dnac_get.pyファイルを作成し、カスタムモジュール用のlibraryディレクトリに格納しました。

dnac_get.py
#!/usr/bin/env python

from __future__ import absolute_import, division, print_function
__metaclass__ = type

from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.dnac.dnac import DnaCenter,dnac_argument_spec

def main():
    _setting_exists = False
    module_args = dnac_argument_spec
    module_args.update(
        url_path=dict(type='str',required=True)
        )

    module = AnsibleModule(
        argument_spec = module_args,
        supports_check_mode = True
        )
    #  Define Static Variables 
    url_path = module.params['url_path']

    # instansiate the dnac class
    dnac = DnaCenter(module)

    # Set API Path 
    dnac.api_path = 'api/v1/' + url_path

    # Send GET request
    output =  dnac.get_obj()

    module.exit_json(**output)

if __name__ == "__main__":
  main()

Inventory/Playbook

Cisco DNA CenterをAnsibleから操作する(uriモジュール編)と同様に、デバイス情報一覧を取得してみます。

inventory_dnac1
[cisco]
DNA_Center ansible_host=sandboxdnac2.cisco.com ansible_port=443

[cisco:vars]
username=[DNA Centerのユーザ名]
password=[DNA Centerのパスワード]

Playbookは、認証トークンの明示的な取得や、URLをフルパスで指定する必要がなくなったため、全体的にシンプルになっています。

playbook_dnac_get2.yml
---

- hosts: cisco
  gather_facts: no
  connection: local

  vars:
    device_list_extracted: [['hostname', 'managementIpAddress', 'platformId', 'softwareVersion', 'role', 'upTime']]

  tasks:
    - name: Get network device list
      dnac_get:
        host: "{{ ansible_host }}"
        port: "{{ ansible_port | int }}"
        username: "{{ username }}"
        password: "{{ password }}"
        url_path: network-device
        validate_certs: false
        use_proxy: false
      register: device_list

    - name: Extract necessary data from the device list
      set_fact:
        device_list_extracted: "{{ device_list_extracted + [[item.hostname, item.managementIpAddress, 
                                   item.platformId, item.softwareVersion, item.role, item.upTime]] }}"
      loop: "{{ device_list.response | flatten(levels=1) }}"

    - name: Display extracted device list
      debug:
        msg: "{{ device_list_extracted }}"

出力結果

前回と同様の結果が出力されました。

(venv)$ ansible-playbook -i inventory_dnac2 playbook_dnac_get2.yml

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

TASK [Get network device list] **********************************************************************************************
ok: [DNA_Center]

TASK [Extract necessary data from the device list] **************************************************************************
ok: [DNA_Center] => (item={'location': None, 'type': 'Cisco 3504 Wireless LAN Controller', 'errorCode': 'ERROR-CONNECTION-CLOSED', 
'family': 'Wireless Controller', 'role': 'ACCESS', 'lastUpdateTime': 1566722713689, (省略)

TASK [Display extracted device list] ****************************************************************************************
ok: [DNA_Center] => {
    "msg": [
        [
            "hostname",
            "managementIpAddress",
            "platformId",
            "softwareVersion",
            "role",
            "upTime"
        ],
        [
            "3504_WLC",
            "10.10.20.51",
            "AIR-CT3504-K9",
            "8.5.140.0",
            "ACCESS",
            "159 days, 23:12:12.00"
        ],
        [
            "leaf1.labb.local",
            "10.10.20.81",
            "C9300-48U",
            "16.6.4a",
            "ACCESS",
            "127 days, 15:20:37.43"
        ],
        [
            "leaf2.labb.local",
            "10.10.20.82",
            "C9300-48U",
            "16.6.4a",
            "ACCESS",
            "126 days, 22:17:53.01"
        ],
        [
            "spine1.abc.in.labb.local",
            "10.10.20.80",
            "WS-C3850-24P-L",
            "16.3.5b",
            "DISTRIBUTION",
            "159 days, 22:57:45.83"
        ]
(省略)
    ]
}

PLAY RECAP ******************************************************************************************************************
DNA_Center                 : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

最後に

今回は簡単なモジュールでしたが、DNA Centerの機能や関連APIはどんどん拡充されていますので、DNA Centerを勉強しつつ、より高度なモジュールにもトライして、OSSにコントリビュートしたいと思います。