Skip to main content
株式会社 エーピーコミュニケーションズ
横地 晃
2019/09/05
#npstudy
ネットワークプログラマビリティ勉強会 #18
2
はじめに
l ネットワーク機器の通常の show コマンドの結果は、
機械にとっては取り扱いにくくなりがち。
l これを解決する、show コマンドの結果を
構造化データにするパーサーと、他ツールとの
組み合わせをご紹介します。
{
"INTF": "GigabitEthernet1",
"IPADDR": "10.10.20.48",
"PROTO": "up",
"STATUS": "up"
},
{
"INTF": "GigabitEthernet2",
"IPADDR": "unassigned",
"PROTO": "down",
"STATUS": "administratively down"
}
show ip interface brief 結果のパース結果例
⾃⼰紹介
3
名前 横地 晃
所属 株式会社エーピーコミュニケーションズ
業務 ネットワーク⾃動化のサービス開発
ブログ てくなべ https://tekunabe.hatenablog.jp
@akira6592
発表・執筆など
l Ansible実践ガイド 第3版
l Software Design 2018年12⽉号 Ansible 特集
l NetOpsCoding#5 × ネットワークプログラマビリティ勉強会#13
第3版
ネットワーク対応も追加
2019年10⽉発売予定
4
パーサーとは
パーサーとは
5
l show コマンドの結果を、機械が取り扱いやすい
構造化データに変換するもの (今回の発表の⽂脈上の説明)
「そもそもネットワーク器機が構造化データを出⼒してくれればいいのでは︖」→ ごもっとも
csr1000v#show ip interface brief
Interface IP-Address OK? Method Status Protocol
GigabitEthernet1 10.10.20.48 YES NVRAM up up
GigabitEthernet2 unassigned YES NVRAM administratively down down
GigabitEthernet3 unassigned YES NVRAM administratively down down
{
"INTF": "GigabitEthernet1",
"IPADDR": "10.10.20.48",
"PROTO": "up",
"STATUS": "up"
},
{
"INTF": "GigabitEthernet2",
"IPADDR": "unassigned",
"PROTO": "down",
"STATUS": "administratively down"
},
{
"INTF": "GigabitEthernet3",
"IPADDR": "unassigned",
"PROTO": "down",
"STATUS": "administratively down"
}
機械が取り扱いやすい
パーサー
今回ご紹介するパーサーたち
6
l TextFSM
l Genie Parser
netmiko
Ansible Genie Parser
TextFSM
パーサー⾃動化ツール
コマンド実⾏ 連携 {
"INTF": "GigabitEthernet1",
"IPADDR": "10.10.20.48",
"PROTO": "up",
"STATUS": "up"
}
変換
⾃動化ツールとの
組み合わせもご紹介
構造化データネットワーク機器
今回の例で利⽤するコマンド結果
7
csr1000v#show ip interface brief
Interface IP-Address OK? Method Status Protocol
GigabitEthernet1 10.10.20.48 YES NVRAM up up
GigabitEthernet2 unassigned YES NVRAM administratively down down
GigabitEthernet3 unassigned YES NVRAM administratively down down
Loopback0 unassigned YES unset up up
Loopback1 unassigned YES unset up up
Loopback2 unassigned YES unset up up
l Cisco IOS-XE の show ip interface brief 結果
環境: Cisco DevNet Sandbox CSRV1000V IOS-XE (16.11.01a)
これをパースします
8
TextFSM
カスタマイズが容易なパーサー
TextFSM とは
9
l Python製のパーサー
◦ https://github.com/google/textfsm
l ntc-templates のテンプレートを利⽤可
◦ プラットフォーム数 23
◦ コマンド数 290
◦ https://github.com/networktocode/ntc-templates
l テンプレートは追加、カスタマイズ可能
l pip install textfsm でインストール
(2019/09/03現在)
TextFSM で利⽤するテンプレート例
10
Value INTF (¥S+)
Value IPADDR (¥S+)
Value STATUS (up|down|administratively down)
Value PROTO (up|down)
Start
^${INTF}¥s+${IPADDR}¥s+¥w+¥s+¥w+¥s+${STATUS}¥s+${PROTO} -> Record
Cisco IOS の show ip interface brief コマンドのパーステンプレート
https://github.com/networktocode/ntc-templates/blob/master/templates/cisco_ios_show_ip_interface_brief.template
正規表現
TextFSM 単体(コード)
11
import textfsm
from pprint import pprint
# テンプレートファイルの読み込み
template = open('./templates/cisco_ios_show_ip_interface_brief.template', 'r')
re_table = textfsm.TextFSM(template)
fsm_results = re_table.ParseText(raw_text_data)
results = list()
# ヘッダーとデータを結合
for item in fsm_results:
results.append(dict(zip(re_table.header, item)))
pprint(results)
https://github.com/google/textfsm/wiki/TextFSM#using-the-library公式サンプル
テンプレートファイル名
コマンド結果は
何かしらで準備しておく
TextFSM 単体(結果)
12
[{'INTF': 'GigabitEthernet1',
'IPADDR': '10.10.20.48',
'PROTO': 'up',
'STATUS': 'up'},
{'INTF': 'GigabitEthernet2',
'IPADDR': 'unassigned',
'PROTO': 'down',
'STATUS': 'administratively down'},
{'INTF': 'GigabitEthernet3',
'IPADDR': 'unassigned',
'PROTO': 'down',
'STATUS': 'administratively down'},
{'INTF': 'Loopback0', 'IPADDR': 'unassigned', 'PROTO': 'up', 'STATUS': 'up'},
{'INTF': 'Loopback1', 'IPADDR': 'unassigned', 'PROTO': 'up', 'STATUS': 'up'},
{'INTF': 'Loopback2', 'IPADDR': 'unassigned', 'PROTO': 'up', 'STATUS': 'up'}]
TextFSM + Netmiko(コード)
13
l Netmiko 2.0.0 から TextFSM 同梱
from netmiko import Netmiko
import os
from pprint import pprint
ios1 = {
"host": ”10.10.20.48",
"device_type": "cisco_ios",
"username": "testuser",
"password": "testpass"
}
os.environ["NET_TEXTFSM"] = "/home/npstudy/templates"
net_connect = Netmiko(**ios1)
result = net_connect.send_command("show ip interface brief", use_textfsm=True)
pprint(result)
実⾏コマンド
テンプレートファイル格納
「ディレクトリ」を環境変数に指定
(デフォルトは ./ntc-templates/templates)
TextFSM をパーサーに使う指定
TextFSM + Netmiko(結果)
14
[{'intf': 'GigabitEthernet1',
'ipaddr': '10.10.20.48',
'proto': 'up',
'status': 'up'},
{'intf': 'GigabitEthernet2',
'ipaddr': 'unassigned',
'proto': 'down',
'status': 'administratively down'},
{'intf': 'GigabitEthernet3',
'ipaddr': 'unassigned',
'proto': 'down',
'status': 'administratively down'},
{'intf': 'Loopback0', 'ipaddr': 'unassigned', 'proto': 'up', 'status': 'up'},
{'intf': 'Loopback1', 'ipaddr': 'unassigned', 'proto': 'up', 'status': 'up'},
{'intf': 'Loopback2', 'ipaddr': 'unassigned', 'proto': 'up', 'status': 'up'}]
TextFSM + Ansible(Playbook)
15
l Ansible 2.4 で parse_cli_textfsm フィルター追加
- hosts: ios
gather_facts: no
vars:
template_file: "./templates/cisco_ios_show_ip_interface_brief.template"
tasks:
- name: show
ios_command:
commands:
- show ip interface brief
register: result
- name: show parsed result
debug:
msg: "{{ result.stdout[0] | parse_cli_textfsm(template_file) }}"
※別途、インベントリ、認証情報の定義が必要
実⾏コマンド
テンプレートファイル名
(vars で定義済み)
要 pip install textfsm
TextFSM + Ansible(結果)
16
ok: [ios1] => {
"msg": [
{
"INTF": "GigabitEthernet1",
"IPADDR": "10.10.20.48",
"PROTO": "up",
"STATUS": "up"
},
{
"INTF": "GigabitEthernet2",
"IPADDR": "unassigned",
"PROTO": "down",
"STATUS": "administratively down"
},
{
"INTF": "GigabitEthernet3",
"IPADDR": "unassigned",
"PROTO": "down",
"STATUS": "administratively down"
},
{
"INTF": "Loopback0",
"IPADDR": "unassigned",
"PROTO": "up",
"STATUS": "up"
},
{
"INTF": "Loopback1",
"IPADDR": "unassigned",
"PROTO": "up",
"STATUS": "up"
},
{
"INTF": "Loopback2",
"IPADDR": "unassigned",
"PROTO": "up",
"STATUS": "up"
}
]
}
17
Genie Parser
Cisco 機器に強いパーサー
Genie Parser とは
18
l Python製テストフレームワーク/ライブラリ
「pyATS/Genie」内のパーサー
◦ https://github.com/CiscoTestAutomation/genieparser
◦ Cisco 社が開発をはじめたもの
l Cisco 機器への対応が充実
◦ プラットフォーム数 8(Cisco 7、Juniper 1)
◦ コマンド数 約1300
◦ https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers
l pip install genie でインストール
(2019/09/03現在)
Genie Parser 単体(コード)
19
testbed:
name: "testbed1"
devices:
csr1000v:
type: catalyst
platform: iosxe
os: "iosxe"
alias: "ios1"
tacacs:
login_prompt: "login:"
password_prompt: "Password:"
username: testuser
passwords:
tacacs: testpass
# enable: testpass
# line: testpass
connections:
ssh:
protocol: ssh
ip: "10.10.20.48"
コマンド結果は
何かしらで準備しておく
testbedファイル(接続情報)
from genie.conf import Genie
from pprint import pprint
testbed = Genie.init("./testbed.yml")
device = testbed.devices["csr1000v"]
device.connect()
output = device.parse("show ip interface brief")
pprint(output)
Testbedファイル
実⾏コマンド
接続先
実⾏コード
Genie Parser 単体(結果1)
20
[2019-09-04 15:30:20,523] +++ csr1000v logfile /tmp/csr1000v-cli-20190904T153020523.log +++
[2019-09-04 15:30:20,524] +++ Unicon plugin iosxe +++
Password:
[2019-09-04 15:30:28,022] +++ connection to spawn: ssh -l developer 10.10.20.48, id: 4458345528 +++
[2019-09-04 15:30:28,023] connection to csr1000v
Welcome to the DevNet Sandbox for CSR1000v and IOS XE
The following programmability features are already enabled:
- NETCONF
- RESTCONF
Thanks for stopping by.
csr1000v#
[2019-09-04 15:30:29,379] +++ initializing handle +++
[2019-09-04 15:30:29,381] +++ csr1000v: executing command 'term length 0' +++
term length 0
csr1000v#
[2019-09-04 15:30:29,647] +++ csr1000v: executing command 'term width 0' +++
term width 0
csr1000v#
[2019-09-04 15:30:29,883] +++ csr1000v: executing command 'show version' +++
show version
Cisco IOS XE Software, Version 16.09.03
...略....
csr1000v#
[2019-09-04 15:30:30,171] +++ csr1000v: config +++
config term
Enter configuration commands, one per line. End with CNTL/Z.
csr1000v(config)#no logging console
csr1000v(config)#line console 0
csr1000v(config-line)#exec-timeout 0
csr1000v(config-line)#end
csr1000v#
[2019-09-04 15:30:32,395] +++ csr1000v: executing command 'show ip interface brief' +++
show ip interface brief
Interface IP-Address OK? Method Status Protocol
GigabitEthernet1 10.10.20.48 YES NVRAM up up
GigabitEthernet2 unassigned YES NVRAM administratively down down
GigabitEthernet3 unassigned YES NVRAM administratively down down
Loopback0 unassigned YES unset up up
Loopback1 unassigned YES unset up up
Loopback2 unassigned YES unset up up
csr1000v#
ログインや ter len 0 などの
ログが流れていく・・・
↓
続く
Genie Parser 単体(結果2)
21
{'interface': {'GigabitEthernet1': {'interface_is_ok': 'YES',
'ip_address': '10.10.20.48',
'method': 'NVRAM',
'protocol': 'up',
'status': 'up'},
'GigabitEthernet2': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'NVRAM',
'protocol': 'down',
'status': 'administratively down'},
'GigabitEthernet3': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'NVRAM',
'protocol': 'down',
'status': 'administratively down'},
'Loopback0': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'},
'Loopback1': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'},
'Loopback2': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'}}}
↓
続き
Genie Parser + netmiko(コード)
22
from netmiko import Netmiko
import os
from pprint import pprint
ios1 = {
"host": ”10.10.20.48",
"device_type": "cisco_ios",
"username": "testuser",
"password": "testpass"
}
net_connect = Netmiko(**ios1)
result = net_connect.send_command("show ip interface brief", use_genie=True)
pprint(result)
実⾏コマンド
l Netmiko 2.4.1 で Genie/pyATS parser サポート
要 pip install genie
Genie Parser を
パーサーに使う指定
Genie Parser + netmiko(結果)
23
{'interface': {'GigabitEthernet1': {'interface_is_ok': 'YES',
'ip_address': '10.10.20.48',
'method': 'NVRAM',
'protocol': 'up',
'status': 'up'},
'GigabitEthernet2': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'NVRAM',
'protocol': 'down',
'status': 'administratively down'},
'GigabitEthernet3': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'NVRAM',
'protocol': 'down',
'status': 'administratively down'},
'Loopback0': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'},
'Loopback1': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'},
'Loopback2': {'interface_is_ok': 'YES',
'ip_address': 'unassigned',
'method': 'unset',
'protocol': 'up',
'status': 'up'}}}
Genie Parser + Ansible(Playbook)
24
l clay584.parse_genie ロールで連携
- hosts: ios
gather_facts: no
vars:
show: show ip interface brief
tasks:
- name: Read in parse_genie role
include_role:
name: clay584.parse_genie
- name: ios command test
ios_command:
commands:
- "{{ show }}"
register: result
- name:
debug:
msg: "{{ result.stdout[0] | parse_genie(command=show, os='iosxe') }}"
※別途、インベントリ、認証情報の定義が必要
あらかじめ
ansible-galaxy install clay584.parse_genie
でインストールしたロールを仕様
実⾏コマンド
(vars で定義済み)
要 ansible-galaxy install clay584.parse_genie
実⾏コマンド
(vars で定義済み)
対象OS
Genie Parser + Ansible(結果)
25
ok: [ios1] => {
"msg": {
“interface”: {
"GigabitEthernet1": {
"interface_is_ok": "YES",
"ip_address": "10.10.20.48",
"method": "NVRAM",
"protocol": "up",
"status": "up"
},
"GigabitEthernet2": {
"interface_is_ok": "YES",
"ip_address": "unassigned",
"method": "NVRAM",1
"protocol": "down",
"status": "administratively down"
},
"GigabitEthernet3": {
"interface_is_ok": "YES",
"ip_address": "unassigned",
"method": "NVRAM",
"protocol": "down",
"status": "administratively down"
},
"Loopback0": {
"interface_is_ok": "YES",
"ip_address": "unassigned",
"method": "unset",
"protocol": "up",
"status": "up"
},
"Loopback1": {
"interface_is_ok": "YES",
"ip_address": "unassigned",
"method": "unset",
"protocol": "up",
"status": "up"
},
"Loopback2": {
"interface_is_ok": "YES",
"ip_address": "unassigned",
"method": "unset",
"protocol": "up",
"status": "up"
}
}
}
}
26
まとめ
まとめ
27
l TextFSM
◦ カスタマイズが容易
l Genie Parser
◦ Cisco 機器に強い
l 使い分け(個⼈的主観)
◦ Cisco の機器が対象なら Genie Parser
◦ それ以外、容易にカスタマイズしたいなら TextFSM
l netmiko や Ansible との連携も便利
参考
28
l TextFSM
◦ netmiko と TextFSM を利⽤してネットワーク機器の show コマンド結果をパースする
◦ https://tekunabe.hatenablog.jp/entry/2018/12/31/netmiko_textfsm
◦ ネットワーク機器のコマンド結果をパースする parse_cli_textfsm フィルタープラグインを試す
◦ https://tekunabe.hatenablog.jp/entry/2017/09/23/parse_cli_textfsm
l Genie Parser
◦ pyATS/Genie : ネットワークテスト⾃動化ツール pyATS & Genie についてとインストール⽅法
◦ https://ccieojisan.net/post-1697/
◦ Genie Parser/OpsによるCisco機器のログ取得・構⽂解析
◦ https://qiita.com/tech_kitara/items/f5c4ae6cbab8e7240f40
◦ Ansible 連携ロール「clay584.parse_genie」の説明
◦ https://developer.cisco.com/codeexchange/github/repo/clay584/parse_genie
l ansible-network.network-engine ロール(今回ご紹介できなかったもの)
◦ command_parser という Ansible ネイティブなパーサーがある
◦ リポジトリ
◦ https://github.com/ansible-network/network-engine