この記事はAnsible Advent Calendar 2019の7日目の記事です。
やってみた
今回はAnsibleを使ってCiscoIOSXRの情報取得を行いたいと思います。
準備
AnsibleでNW機器へ接続する前にまずは以下の3点を確認します。
これはNW機器でなくても同じことだと思います。
- 機器は何か?
- どんなモジュールで実装するか?
- 接続方式は何か?
接続方式 | モジュール | やりたいこと |
---|---|---|
netconf | netconf_get | show runを取る |
network_cli | iosxr_command | show runを取る |
network_cli | iosxr_command | ルートがあるか調べる |
環境説明
ansible == 2.8.7
python == 3.7.5
接続先
今回はCiscoDevnetのSandBoxにあるIOS XR Programmabilityを利用します
DevNetの環境があればだれでも使うことが可能です。
共有と占有のものがあり、今回は共有のもの利用します(なのでちょっと反応が遅い)
※占有のものを利用するには、予約が必要です、こちらもアカウントがあれば簡単にできます
※占有のものを利用する際はCiscoAnyConnectも必要になります。
show runを取る
それではさっそく、show runを取得してみましょう。
今回は2通りの方法で挑戦してみました。
inventoryの内容説明
[iosxr]
sbx-iosxr-mgmt.cisco.com
group_varsの設定は以下、
今回は接続しない方式のものはコメントアウトして書き換えてます(楽だったので)
#ansible_connection: network_cli
ansible_connection: netconf
ansible_network_os: iosxr
#ansible_port: 8181
ansble_port: 10000
ansible_user: admin
ansible_password: C1sco12345
ansible_python_interpreter: "/usr/bin/python"
作成したPlaybook
メインのPlaybookはこんなシンプルに
ansibleのversionが2.8なのでgather_factsはnoで
---
- hosts: all
gather_facts: no
roles:
- send_command
roleの中身はこんな感じ
Ansible_connectionとAnsible_network_osで対象のTaskを選択
---
- name: iosxr_commandモジュールテスト(show_command)
iosxr_command:
commands: "{{ item }}"
register: cli_result
loop: "{{ show_commands }}"
when:
- ansible_connection == "network_cli"
- ansible_network_os == "iosxr"
- name: Network_cliでConfig取得
debug:
msg: "{{ item.stdout }}"
loop: "{{ cli_result.results }}"
loop_control:
label: "commands"
when:
- ansible_connection == "network_cli"
- ansible_network_os == "iosxr"
- name: NetconfでConfigを取得
netconf_get:
source: running
register: netconf_result
when: ansible_connection == "netconf"
- name: 表示
debug:
msg: "{{ netconf_result.stdout }}"
when: ansible_connection == "netconf"
- name: nxos_commandモジュールテスト(show_command)
nxos_command:
commands: "{{ item }}"
register: cli_result
loop: "{{ show_commands }}"
when:
- ansible_connection == "network_cli"
- ansible_network_os == "nxos"
- name: commad実行結果表示
debug:
msg: "{{ item.stdout }}"
loop: "{{ cli_result.results }}"
loop_control:
label: "commands"
when:
- ansible_connection == "network_cli"
- ansible_network_os == "nxos"
netconfで取ってみる
まずはncclientをpipでインストールする必要があります。
pip install ncclient
実行結果
22:32:36 IOS_Autamation $ansible-playbook -i inventory/iosxr.ini test.yml
PLAY [all] *************************************************************************************************************************************************************************************************
TASK [send_command : iosxr_commandモジュールテスト(show_command)] **************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show clock)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show version)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show run)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show ip route)
TASK [send_command : Network_cliでConfig取得] *****************************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com]
TASK [send_command : NetconfでConfigを取得] ********************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com]
TASK [send_command : 表示] ***********************************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com] =>
msg: |-
<ns0:data xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:ns1="http://cisco.com/ns/yang/Cisco-IOS-XR-man-xml-ttyagent-cfg"
...snip
<ns1:xr-xml>
<ns1:agent>
<ns1:tty>
<ns1:enable />
<ns1:iteration-size>0</ns1:iteration-size>
</ns1:tty>
</ns1:agent>
</ns1:xr-xml>
<ns1:netconf>
<ns1:agent>
<ns1:tty>
<ns1:enable />
</ns1:tty>
</ns1:agent>
</ns1:netconf>
<ns2:tpa>
<ns2:vrf-names>
<ns2:vrf-name>
<ns2:vrf-name>default</ns2:vrf-name>
<ns2:address-family>
<ns2:ipv4>
<ns2:default-route>mgmt</ns2:default-route>
</ns2:ipv4>
</ns2:address-family>
</ns2:vrf-name>
</ns2:vrf-names>
</ns2:tpa>
<ns3:router-static>
<ns3:default-vrf>
<ns3:address-family>
<ns3:vrfipv4>
<ns3:vrf-unicast>
<ns3:vrf-prefixes>
<ns3:vrf-prefix>
<ns3:prefix>0.0.0.0</ns3:prefix>
<ns3:prefix-length>0</ns3:prefix-length>
<ns3:vrf-route>
<ns3:vrf-next-hop-table>
<ns3:vrf-next-hop-next-hop-address>
<ns3:next-hop-address>10.10.20.254</ns3:next-hop-address>
</ns3:vrf-next-hop-next-hop-address>
</ns3:vrf-next-hop-table>
</ns3:vrf-route>
</ns3:vrf-prefix>
</ns3:vrf-prefixes>
</ns3:vrf-unicast>
</ns3:vrfipv4>
</ns3:address-family>
</ns3:default-vrf>
</ns3:router-static>
....snip
<ns30:lldp>
<ns30:config>
<ns30:enabled>false</ns30:enabled>
</ns30:config>
</ns30:lldp>
</ns0:data>
TASK [send_command : nxos_commandモジュールテスト(show_command)] ***************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show clock)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show version)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show run)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show ip route)
TASK [send_command : commad実行結果表示] *************************************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com]
PLAY RECAP *************************************************************************************************************************************************************************************************
sbx-iosxr-mgmt.cisco.com : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
22:35:07 IOS_Autamation $
無事取れました、マルチベンダでまだ試してはいませんが、思ったよりわかりやすいといった印象。
ACIとかPaloでXML見る機会が多かったかな?
駆動型のネットワーク(こうしたいと定義した通りになる)を実現するために、Netconfは今後少しずつ広がりを見せていくのではないでしょうか。
今回はneutron_モジュールを利用しましたが、各ベンダモジュール(ios_,junos_*)も物によってはnetconfに対応しているようです。
network_cliで取ってみる
今度はnetwork_cliで情報取得をしてみましょう
role/group_varsには下記のmain.ymlが格納されており、send_commandのroleが呼び出されます。
※おまけで色々コマンド取ってます
---
show_commands:
- show clock
- show version
- show runnnig-config
- show ip route
始める前にgroup_varsをちょちょっと書き換えます。
---
ansible_connection: network_cli
#ansible_connection: netconf
ansible_network_os: iosxr
ansible_port: 8181
#ansible_port: 10000
ansible_user: admin
ansible_password: C1sco12345
ansible_python_interpreter: "/usr/bin/python"
実行結果
22:32:15 IOS_Autamation $ansible-playbook -i inventory/iosxr.ini test.yml
PLAY [all] *************************************************************************************************************************************************************************************************
TASK [send_command : iosxr_commandモジュールテスト(show_command)] **************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com] => (item=show clock)
ok: [sbx-iosxr-mgmt.cisco.com] => (item=show version)
ok: [sbx-iosxr-mgmt.cisco.com] => (item=show run)
ok: [sbx-iosxr-mgmt.cisco.com] => (item=show ip route)
TASK [send_command : Network_cliでConfig取得] *****************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com] => (item=commands) =>
msg:
- 15:03:08.279 UTC Fri Dec 6 2019
ok: [sbx-iosxr-mgmt.cisco.com] => (item=commands) =>
msg:
- |-
Cisco IOS XR Software, Version 6.5.3
Copyright (c) 2013-2019 by Cisco Systems, Inc.
Build Information:
Built By : ahoang
Built On : Tue Mar 26 06:52:25 PDT 2019
Built Host : iox-ucs-019
Workspace : /auto/srcarchive13/prod/6.5.3/xrv9k/ws
Version : 6.5.3
Location : /opt/cisco/XR/packages/
cisco IOS-XRv 9000 () processor
System uptime is 4 days 8 hours 37 minutes
ok: [sbx-iosxr-mgmt.cisco.com] => (item=commands) =>
msg:
- |-
Building configuration...
!! IOS XR Configuration version = 6.5.3
!! Last configuration change at Fri Dec 6 15:01:19 2019 by admin
!
hostname iosxr1
domain name abc.inc
username admin
group root-lr
group cisco-support
secret 5 $1$oN8e$ft916PCBogrqPKt59kepW0
!
tpa
vrf default
address-family ipv4
default-route mgmt
!
!
!
line console
exec-timeout 0 0
absolute-timeout 0
session-timeout 0
!
line default
exec-timeout 0 0
absolute-timeout 0
session-timeout 0
transport input ssh
!
call-home
service active
contact smart-licensing
profile CiscoTAC-1
active
destination transport-method http
!
!
interface Loopback100
description ***MERGE LOOPBACK 100****
ipv4 address 1.1.1.100 255.255.255.255
!
interface Loopback200
description ***MERGE LOOPBACK 200****
ipv4 address 1.1.1.200 255.255.255.255
!
interface MgmtEth0/RP0/CPU0/0
ipv4 address 10.10.20.175 255.255.255.0
!
interface GigabitEthernet0/0/0/0
shutdown
!
interface GigabitEthernet0/0/0/1
shutdown
!
interface GigabitEthernet0/0/0/2
shutdown
!
interface GigabitEthernet0/0/0/3
shutdown
!
interface GigabitEthernet0/0/0/4
shutdown
!
interface GigabitEthernet0/0/0/5
shutdown
!
interface GigabitEthernet0/0/0/6
shutdown
!
router static
address-family ipv4 unicast
0.0.0.0/0 10.10.20.254
!
!
xml agent tty
iteration off
!
netconf agent tty
!
netconf-yang agent
ssh
!
ssh server v2
ssh server vrf default
ssh server netconf vrf default
end
ok: [sbx-iosxr-mgmt.cisco.com] => (item=commands) =>
msg:
- |-
Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path
D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP
i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2
ia - IS-IS inter area, su - IS-IS summary null, * - candidate default
U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP
A - access/subscriber, a - Application route
M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path
Gateway of last resort is 10.10.20.254 to network 0.0.0.0
S* 0.0.0.0/0 [1/0] via 10.10.20.254, 4d08h
L 1.1.1.100/32 is directly connected, 4d08h, Loopback100
L 1.1.1.200/32 is directly connected, 4d08h, Loopback200
C 10.10.20.0/24 is directly connected, 4d08h, MgmtEth0/RP0/CPU0/0
L 10.10.20.175/32 is directly connected, 4d08h, MgmtEth0/RP0/CPU0/0
TASK [send_command : NetconfでConfigを取得] ********************************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com]
TASK [send_command : 表示] ***********************************************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com]
TASK [send_command : nxos_commandモジュールテスト(show_command)] ***************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show clock)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show version)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show run)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=show ip route)
TASK [send_command : commad実行結果表示] *************************************************************************************************************************************************************************
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com] => (item=commands)
skipping: [sbx-iosxr-mgmt.cisco.com]
PLAY RECAP *************************************************************************************************************************************************************************************************
sbx-iosxr-mgmt.cisco.com : ok=2 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
22:32:36 IOS_Autamation $
こちらはよくみた形式ですね。
非常に親しみやすい表示で安心します
取得くらいなら、簡単に実装できることがお分かり頂けたかと思います。
ルートを調べる
pyATS/genieのroleをansible-galaxyからinstallし、show ip routeをgenieにparse
assertモジュールを使って判定をさせてます。
roleをinstall
ansible-galaxy install clay584.parse_genie
pyatsとgenieをinstall
pip install pays
pip install genie
or
pip install pays[full]
実装したPlaybook
---
- hosts: iosxr
gather_facts: false
connection: network_cli
vars:
command: show route ipv4
tasks:
- name: Genieのroleをinclude
include_role:
name: clay584.parse_genie
- name: Route取得
iosxr_command:
commands: "{{ command }}"
register: response1
- name: Genieにパースして変数にする(set_fact)
set_fact:
result1: "{{ response1['stdout'][0] | parse_genie(command='show route ipv4',os='iosxr') }}"
- name: コンフィグ確認
assert:
that:
- '"0.0.0.0/0" in result1.vrf.default.address_family.ipv4.routes'
success_msg:
- 'ルーティングテーブルに0.0.0.0/0が含まれているね'
実行結果(成功)
23:10:12 IOS_Autamation $ansible-playbook -i inventory/iosxr.ini genie_test.yml
PLAY [iosxr] ***********************************************************************************************************************************************************************************************
TASK [Genieのroleをinclude] **********************************************************************************************************************************************************************************
TASK [Route取得] *********************************************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com]
TASK [Genieにパースして変数にする(set_fact)] **************************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com]
TASK [コンフィグ確認] *********************************************************************************************************************************************************************************************
ok: [sbx-iosxr-mgmt.cisco.com] => changed=false
msg:
- ルーティングテーブルに0.0.0.0/0が含まれているね
PLAY RECAP *************************************************************************************************************************************************************************************************
sbx-iosxr-mgmt.cisco.com : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
23:10:30 IOS_Autamation $
genieにパースすることでshow ~~コマンドを辞書形式に変換してくれます。
これにより、判定させることが容易になります。
まとめ
簡単に動かせる
動かすだけなら簡単でした、今回初めて接続方式にnetconfを利用してみましたが、
これは使いこなせれば非常に便利そうです。
ベンダによらず情報取得/設定/削除ができ、Playbookもキレイにできそうだなぁ
ですが、データ構造体YANGやXMLの理解が必要になるのかとふんわり思ってます(ここが難しいそう)
ansibleのversionも2.8を利用しましたが、2.9からはgather_factで情報の取得が構成情報の取得が可能となり
さらに活用の幅も広がりそうです。
今回の内容はわりと入門だったと思います、ぜひ皆さんもAnsible触っていきましょう!