clay584.parse_genie
パースジェニー
注意!!! - コマンドのパースに失敗した場合、パースライブラリにバグがある可能性があります。その場合は、こちらに問題を報告してください。
ネットワークジェニーフィルタは、すべてのCiscoネットワークオペレーティングシステムからの非構造化のネットワークCLIコマンド出力を受け取り、構造化データを出力します。他のネットワークCLIパーサ(parse_cli、parse_cli_textfsm)に似ていますが、このパーサはCiscoが開発した非常に成熟した堅牢なライブラリ「ジェニー」に基づいています(基盤となるフレームワークはpyATSです)。これにより、1200以上のパーサが提供され、構成とCLI出力を標準的でOSに依存しないデータモデルに正規化された構造化データに変換します。
ジェニーライブラリは、従来のパースよりもはるかに少ないコードで表形式および非表形式の自由形式テキストをパースするエンジンとしても機能します。したがって、Ciscoデバイスだけでなく、他のベンダーの出力をパースするために使用できます。ただし、カスタムパーサを書く必要があります。このリリースにはカスタムパーサを使用する機能は含まれていません。サポートされるパーサは、ユーザーがAnsibleコントロールマシンにインストールしたジェニーのリリースに含まれるものです。
サポートされているオペレーティングシステムとコマンドのリスト、ならびに特定のコマンドに対して返されるフィールドとデータ型を詳述するデータのスキーマ定義は、以下のリンクからCiscoで入手できます。
https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/parsers
前提条件
このプラグインでは、次のものが必要です:
- Python 3.4以上
- pyATSおよびジェニーパッケージ
- Ansible 2.7以上(他の要件が満たされていれば、古いバージョンでも動作するはずです)
インストール
フィルタプラグインがプレイブックで機能することを確認するために、以下の手順に従ってください:
- プレイブック用のディレクトリを作成し、移動します。
mkdir network_ops && cd network_ops
- 仮想環境を作成します。
python3 -m venv .venv
- 仮想環境をアクティブにします。
source .venv/bin/activate
- Ansibleをインストールします。
pip install ansible
- ジェニーとpyATSをインストールします。
pip install genie
- Ansible Galaxyからparse_genieロールをインストールします。
ansible-galaxy install clay584.parse_genie
AnsibleからジェニーOSへのマッピング
以下は、Ansibleの ansible_network_os
からジェニーの os
へのマッピングです:
AnsibleネットワークOS | ジェニーOS |
---|---|
ios | ios, iosxe |
nxos | nxos |
iosxr | iosxr |
junos | junos |
もしIOSまたはIOS-XEを使用している場合、AnsibleはIOSとIOS-XEを同じものと見なすため、ansible_network_os = ios
となります。しかし、ジェニーはCLI出力を正しくパースするために、IOSかIOS-XEのどちらかを特定する必要があります。このフィルタプラグインに ansible_network_os
を渡すと、parse_genieは最初に os=ios
でジェニーを使用してパースを試み、失敗した場合は次に os=iosxe
で試みます。
プレイブックを作成する際にこの点を念頭に置いておいてください。parse_genieには本当のOSを渡す方が良いルールでしょう。それを行うためには、他のインベントリ変数またはhost_varを保持し、各ネットワークデバイスのためにジェニーOSを指定し、その変数をparse_genieのOSとして使用することができます。
使用法
フィルタプラグインをプレイブックで利用する前に、parse_genieロールを読み込むことを確認してください。
...省略...
tasks:
- name: parse_genieロールを読み込む
include_role:
name: clay584.parse_genie
...省略...
簡単な例
ネットワークデバイスのCLIコマンドの出力を変換するには、次のように parse_genie
フィルタを使用します(省略形のCLIコマンドは使用しないでください)。
Cisco IOS-XEデバイスの show version
コマンドのCLI出力を構造化データに変換する例::
{{ cli_output | parse_genie(command='show version', os='iosxe') }}
より深い抽象化を行いたい場合は、platform
を parse_genie
に追加できます。
{{ cli_output | parse_genie(command='show version', os='iosxe', platform='asr1k') }}
上記の例は次のようになります:
{
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "virtual hard disk"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "WebUI ODM Files"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "production image",
"last_reload_reason": "Reload Command",
"license_level": "ax",
"license_type": "Default. No valid license found.",
"main_mem": "1126522",
"mem_size": {
"non-volatile configuration": "32768",
"physical": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutes",
"uptime_this_cp": "3 minutes",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
フル例 #1
プレイブック:
---
- hosts: localhost
connection: local
vars:
show_version_output: |
Cisco IOS XE Software, Version 16.05.01b
Cisco IOS Software [Everest], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.5.1b, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2017 by Cisco Systems, Inc.
Compiled Tue 11-Apr-17 16:41 by mcpre
Cisco IOS-XEソフトウェア、著作権 (c) 2005-2017 by Cisco Systems, Inc.
All rights reserved. Certain components of Cisco IOS-XEソフトウェアはGNU General Public License ("GPL") Version 2.0の下でライセンスされています。
GPLバージョン2.0の下でライセンスされたソフトウェアコードは、無保証の無料ソフトウェアとして提供されます。
あなたはこのGPLコードをGPLバージョン2.0の条件下で再配布および/または変更することができます。
詳細については、IOS-XEソフトウェアに付随する文書または "ライセンス通知" ファイル、またはIOS-XEソフトウェアに付随するフライヤーに記載されている適用可能なURLを参照してください。
ROM: IOS-XE ROMMON
host-172-16-1-96のアップタイムは2分です。
この制御プロセッサのアップタイムは3分です。
システムはリロードによってROMに戻されました。
システムイメージファイルは "bootflash:packages.conf" です。
最後のリロード理由: リロードコマンド。
この製品には暗号機能が含まれており、輸入、輸出、移転及び使用に関する米国及び現地の法律の対象となります。
Ciscoの暗号製品の配信は、暗号の輸入、輸出、配信または使用についての第三者の権限を意味するものではありません。
輸入業者、輸出業者、ディストリビューター及びユーザーは、米国及び現地の法律の遵守に責任を負います。
本製品を使用することにより、あなたは適用法令を遵守することに同意したことになります。
米国及び現地の法令を遵守できない場合は、直ちにこの製品を返却してください。
Ciscoの暗号製品に関する米国の法律の要約は、以下のURLで確認できます:
http://www.cisco.com/wwl/export/crypto/tool/stqrg.html
さらなる支援が必要な場合は、[email protected]までメールを送信してお問い合わせください。
ライセンスレベル: ax
ライセンスタイプ: デフォルト。 有効なライセンスが見つかりませんでした。
次回リロードライセンスレベル: ax
cisco CSR1000V (VXE)プロセッサ (revision VXE) は1126522K/3075Kバイトのメモリを持っています。
プロセッサーボードID 9TKUWGKX5MO
2つのギガビットイーサネットインターフェース
32768Kバイトの不揮発性設定メモリ。
3018840Kバイトの物理メモリ。
bootflash:での仮想ハードディスクは7774207Kバイトです。
webui:ではWebUI ODMファイルは0Kバイトです。
設定レジスタは0x2102です。
tasks:
- name: parse_genieロールを読み込む
include_role:
name: clay584.parse_genie
- name: ジェニーフィルタのデバッグ
debug:
msg: "{{ show_version_output | parse_genie(command='show version', os='iosxe') }}"
delegate_to: localhost
出力:
$ ansible-playbook -i inventory debug.yml
PLAY [localhost] *************************************************************************
TASK [ファクト収集] **********************************************************************
ok: [localhost]
TASK [parse_genieロールを読み込む] *******************************************************
TASK [ジーニーフィルタのデバッグ] ******************************************************
ok: [localhost -> localhost] => {
"msg": {
"version": {
"chassis": "CSR1000V",
"chassis_sn": "9TKUWGKX5MO",
"curr_config_register": "0x2102",
"disks": {
"bootflash:.": {
"disk_size": "7774207",
"type_of_disk": "virtual hard disk"
},
"webui:.": {
"disk_size": "0",
"type_of_disk": "WebUI ODM Files"
}
},
"hostname": "host-172-16-1-96",
"image_id": "X86_64_LINUX_IOSD-UNIVERSALK9-M",
"image_type": "production image",
"last_reload_reason": "Reload Command",
"license_level": "ax",
"license_type": "Default. No valid license found.",
"main_mem": "1126522",
"mem_size": {
"non-volatile configuration": "32768",
"physical": "3018840"
},
"next_reload_license_level": "ax",
"number_of_intfs": {
"Gigabit Ethernet": "2"
},
"os": "IOS-XE",
"platform": "Virtual XE",
"processor_type": "VXE",
"rom": "IOS-XE ROMMON",
"rtr_type": "CSR1000V",
"system_image": "bootflash:packages.conf",
"uptime": "2 minutes",
"uptime_this_cp": "3 minutes",
"version": "16.5.1b,",
"version_short": "16.5"
}
}
}
フル例 #2
プレイブック:
---
- hosts: csr1000v
gather_facts: False
tasks:
- name: parse_genieロールを読み込む
include_role:
name: clay584.parse_genie
- name: デバイスからデータを取得
ios_command:
commands: show arp vrf Mgmt-intf
register: arp_output
- name: 構造化データを出力
debug:
msg: "{{ arp_output['stdout'][0] | parse_genie(command='show arp vrf Mgmt-intf', os='iosxe') }}"
delegate_to: localhost
出力:
$ ansible-playbook -i inventory playbook.yml
PLAY [csr1000v] **************************************************************************
TASK [parse_genieロールを読み込む] *******************************************************
TASK [デバイスからデータを取得] *******************************************************
ok: [csr1000v]
TASK [構造化データを出力] ***************************************************************
ok: [csr1000v -> localhost] => {
"msg": {
"interfaces": {
"GigabitEthernet1": {
"ipv4": {
"neighbors": {
"172.16.1.111": {
"age": "0",
"ip": "172.16.1.111",
"link_layer_address": "5e00.4004.0000",
"origin": "dynamic",
"protocol": "Internet",
"type": "ARPA"
},
"172.16.1.114": {
"age": "-",
"ip": "172.16.1.114",
"link_layer_address": "5e00.4001.0000",
"origin": "static",
"protocol": "Internet",
"type": "ARPA"
}
}
}
}
}
}
}
一般的な表形式のパース
Ciscoジェニーは、1200のコマンドをサポートしており、数を増やしていますが、Ciscoにより開発されたパーサがないshowコマンドの場合、一般的な表形式のパース機能があります。ジェニーの表形式パース機能に関する詳細は、oper_fill_tabularの文書を参照してください。
表形式パースの仕組み
パーサが構築されている場合は、コマンドの出力をパースするために必要なのは、command
、command output
、os
の3つだけです。しかし、パーサが構築されていない場合は、コマンド出力をパースする際の追加情報を指定する必要があります。この追加データは二つの要素からなります:
- ヘッダー - コマンドの出力に示される列ヘッダー。
- インデックス - パーサが返す辞書アイテムのキー。
以下の例を検討します:
- コマンド:
show ip sla summary
- コマンド出力:
IPSLAs Latest Operation Summary
Codes: * active, ^ inactive, ~ pending
All Stats are in milliseconds. Stats with u are in microseconds
ID Type Destination Stats Return Last
Code Run
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK 20 seconds ago
*2 icmp-echo 10.0.0.2 RTT=1 OK 3 seconds ago
- ヘッダー -
ID
、Type
、Destination
、Stats
、Return Code
、Last Run
。 - インデックス - このデータのインデックスとして
ID
列を使用する。 - パーサ出力:
{'*1': {'Destination ': '10.0.0.2',
'ID ': '*1',
'Last Run': '20 seconds ago',
'Return Code': 'OK',
'Stats ': 'RTT=900u',
'Type ': 'udp-jitter'},
'*2': {'Destination ': '10.0.0.2',
'ID ': '*2',
'Last Run': '3 seconds ago',
'Return Code': 'OK',
'Stats ': 'RTT=1',
'Type ': 'icmp-echo'}}
表形式パースを使用する準備
この表形式パースを使用するには、まず与えられたOSのコマンドに対してheaders
とindex
をAnsibleプレイブックで読み込める形式に構築します。そのために、プレイブック内に以下の形式のvarsファイルを作成する必要があります。これはOSごとにコマンドで整理され、各コマンドの下にヘッダーとインデックスが定義されています。各ネットワークOSに対して、任意の数のコマンドをこのデータ構造内で定義できます。
parse_genie:
ios:
"show ip sla summary":
headers:
- - ID
- Type
- Destination
- Stats
- Return
- Last
- - ''
- ''
- ''
- ''
- Code
- Run
index:
- 0
iosxe:
"show ip sla summary":
headers:
- - ID
- Type
- Destination
- Stats
- Return
- Last
- - ''
- ''
- ''
- ''
- Code
- Run
index:
- 1
上記のyaml形式のPython相当コードは:
python_dict = {
"parse_genie": {
"ios": {
"show ip sla summary": {
"headers": [
[
"ID",
"Type",
"Destination",
"Stats",
"Return",
"Last"
],
[
"",
"",
"",
"",
"Code",
"Run"
]
],
"index": [
0
]
}
},
"iosxe": {
"show ip sla summary": {
"headers": [
[
"ID",
"Type",
"Destination",
"Stats",
"Return",
"Last"
],
[
"",
"",
"",
"",
"Code",
"Run"
]
],
"index": [
1
]
}
}
}
}
プレイブック内でタブularパーサを呼び出す
一般的な表形式コマンドとそのヘッダーおよびインデックスを定義した今、プレイブックから実際に呼び出すことができます。
まず、一般的なコマンドパースのメタデータが含まれたvarsファイルを読み込みます。
- name: 一般的なコマンドメタデータを持つvarsファイルを読み込む
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
次に、コマンド出力を parse_genie
に渡しますが、いくつかの追加パラメータを持たせます。
- name: 一般的な表形式コマンド出力をパースする
debug:
msg: "{{ command_output | parse_genie(command='show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
結果として得られる出力は次のようになります。
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"Destination ": "10.0.0.2",
"ID ": "*1",
"Last Run": "20 seconds ago",
"Return Code": "OK",
"Stats ": "RTT=900u",
"Type ": "udp-jitter"
},
"*2": {
"Destination ": "10.0.0.2",
"ID ": "*2",
"Last Run": "3 seconds ago",
"Return Code": "OK",
"Stats ": "RTT=1",
"Type ": "icmp-echo"
}
}
}
フル例 #1
プレイブック:
---
- hosts: localhost
connection: local
vars:
out_ios_sla: |
IPSLAs Latest Operation Summary
Codes: * active, ^ inactive, ~ pending
All Stats are in milliseconds. Stats with u are in microseconds
ID Type Destination Stats Return Last
Code Run
------------------------------------------------------------------------------------------------
*1 udp-jitter 10.0.0.2 RTT=900u OK 20 seconds ago
*2 icmp-echo 10.0.0.2 RTT=1 OK 3 seconds ago
tasks:
- name: Parse Genieロールを読み込む
include_role:
name: clay584.parse_genie
- name: 一般的なコマンドメタデータを持つvarsファイルを読み込む
include_vars:
file: parse_genie_generic_commands.yml
name: parse_genie
- name: 一般的なタブ形式データのためのジェニーフィルタをテストする
debug:
msg: "{{ out_ios_sla | parse_genie(command='test show ip sla summary', os='ios', generic_tabular=True, generic_tabular_metadata=parse_genie) }}"
delegate_to: localhost
parse_genie_generic_commands.yml
の内容:
---
parse_genie:
ios:
"test show ip sla summary":
headers:
- - ID
- Type
- Destination
- Stats
- Return
- Last
- - ''
- ''
- ''
- ''
- Code
- Run
index:
- 0
iosxe:
"test show ip sla summary":
headers:
- - ID
- Type
- Destination
- Stats
- Return
- Last
- - ''
- ''
- ''
- ''
- Code
- Run
index:
- 1
プレイブック出力:
PLAY [localhost] ******************************************************************************************************************************************************************************************************************************************************************
TASK [ファクト収集] ************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Parse Genieロールを読み込む] ***************************************************************************************************************************************************************************************************************************************************
TASK [varsを読み込む] ***************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [一般的なタブ形式データのためのジェニーフィルタをテストする] *************************************************************************************************************************************************************************************************************
ok: [localhost -> localhost] => {
"msg": {
"*1": {
"Destination ": "10.0.0.2",
"ID ": "*1",
"Last Run": "20 seconds ago",
"Return Code": "OK",
"Stats ": "RTT=900u",
"Type ": "udp-jitter"
},
"*2": {
"Destination ": "10.0.0.2",
"ID ": "*2",
"Last Run": "3 seconds ago",
"Return Code": "OK",
"Stats ": "RTT=1",
"Type ": "icmp-echo"
}
}
}
PLAY RECAP ************************************************************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
開発
開発環境をセットアップします:
- リポジトリをクローンして移動します。
git clone https://github.com/clay584/parse_genie.git && cd parse_genie
- 仮想環境を作成します。
python3 -m venv .venv
- 仮想環境をアクティブにします。
source .venv/bin/activate
- Ansibleをインストールします。
pip install ansible
- ジェニーとpyATSをインストールします。
pip install genie
- yamllintをインストールします。
pip install yamllint
テスト
ローカルでテストするためのコマンドを実行します:
- すべてのYAMLファイルをリンティングします。
yamllint -c yamllint_config.yml *
- テストプレイブックを実行します。
ansible-playbook tests/test.yml --connection=local -i tests/inventory
プッシング
Ansible Galaxyはタグで動作します。
git commit -m"whatever'
git tag -a X.X.X
- X.X.Xはセマンティックバージョニング番号です。git push origin master
git push X.X.X