TextFSM
というパーサ向けにネットワーク機器のshowコマンドの結果をパースするテンプレート集NTC-Templates
があります。新規テンプレートを数件PR出してマージされたので、PRを出す流れとテンプレート作成時のポイントをまとめました。基本は開発ガイドラインに従って開発を行います。
環境準備
Pythonのパッケージ管理ソフトのpoetry
とDocker
を予めインストールしておきます。
Ubuntuの場合はバージョンが古いもののaptでインストール可能です。
sudo apt install python3-poetry
開発の流れ
リポジトリ準備
リポジトリをforkしてgit clone
後、master
からブランチを切ります。
TextFSMテンプレート
ntc_templates/templates
フォルダ内に{ベンダー名}_{OS名}_{コマンド名}.textfsm
というファイル名でTextFSMテンプレートを作成します。
ファイル名の例
-
cisco_ios_show_ip_route.textfsm
:Cisco IOSのshow ip route
コマンド -
cisco_nxos_show_interface_brief.textfsm
:Cisco NXOSのshow interface bried
コマンド -
juniper_junos_show_vlans.textfsm
:Juniper junosのshow vlans
こまn
下記は私が作成したテンプレートの例です。
Value Required VLAN_ID (\d+)
Value VLAN_NAME (\S+)
Value List INTERFACES (\S+\s+\d+(\s+\d+)?)
Start
^VID\s+Interface\s+Tag\s+Type\s+Description
^---- -> VLANS
^Total\s+Count
^\s*$$
^. -> Error
VLANS
^\d+ -> Continue.Record
^${VLAN_ID}\s+${INTERFACES}\s+\S+\s+\S+\s+${VLAN_NAME}\s*$$
^\s+${INTERFACES}\s+\S+\s*$$
^\s*$$ -> Start
^. -> Error
indexファイル
ntc_templates/templates/index
ファイルがテンプレートの一覧となっており、他のテンプレートに倣って記述します。記載順序が決められおり、守らないとテストでNGとなります。
- ベンダー名、OS名のアルファベット順
- テンプレート名の長い順 (長さが等しい場合はアルファベット順)
- OS間に空行を入れる
fortinet_execute_ping.textfsm, .*, fortinet, exec[[ute]] ping
fortinet_execute_time.textfsm, .*, fortinet, exec[[ute]] ti[[me]]
fsas_sir_show_system_information.textfsm, .*, fsas_sir, sh[[ow]] sys[[tem]] i[[nformation]]
fsas_sir_show_ip_ospf_neighbor.textfsm, .*, fsas_sir, sh[[ow]] ip ospf nei[[ghbor]]
fsas_sir_show_ip_route.textfsm, .*, fsas_sir, sh[[ow]] ip ro[[ute]]
fsas_sir_show_ether.textfsm, .*, fsas_sir, sh[[ow]] eth[[er]]
fsas_sir_show_vlan.textfsm, .*, fsas_sir, sh[[ow]] vl[[an]]
hp_comware_display_lldp_neighbor-information_verbose.textfsm, .*, hp_comware, di[[splay]] ll[[dp]] n[[eighbor-information]] v[[erbose]]
hp_comware_display_lldp_neighbor-information_list.textfsm, .*, hp_comware, di[[splay]] ll[[dp]] n[[eighbor-information]] l[[ist]]
hp_comware_display_ip_vpn-instance_instance-name.textfsm, .*, hp_comware, di[[splay]] ip vpn[[-instance]] in[[instance-name]]
テストデータ
開発対象のコマンドの出力結果をtests/{ベンダー名}_{OS名}/コマンド名/
フォルダ配下に.raw
ファイルを作成し記載します。.raw
ファイルのファイル名はテンプレートのファイル名をベースにしていることが多いです。.raw
ファイルは機種やバージョンによって複数用意しても大丈夫です。実行コマンドの行は除いて出力結果のみを記載します。
VID Interface Tag Type Description
---- ------------------ ------------- -------- --------------------------------
1 ether 1 1 untagged port default
2 ether 2 1 untagged port lan2
ether 2 2 untagged
ether 2 3 untagged
501 pseudo-ether 1 untagged port wwan
1005 ether 2 1 dot1q-tagged port v1005
Total Count : 4
テンプレート変換結果
テストデータをテンプレートでパースした結果をYAMLファイルとして保存する必要があります。YAMLファイルの作成には開発用コマンドを使用します。
事前に環境を準備します。
# 仮想環境の作成と開発に必要なパッケージのインストール
poetry install
# 仮想環境に入る
poetry shell
# テスト用Dockerコンテナの作成
invoke build
下記コマンドでYAMLファイルを生成します。
# 単一ファイルから生成
invoke gen-yaml-file <.rawファイル>
# フォルダを指定して一括生成
invoke gen-yaml-folder <フォルダ>
下記のようなYAMLファイルが生成されます。
---
parsed_sample:
- interfaces:
- "ether 1 1"
vlan_id: "1"
vlan_name: "default"
- interfaces:
- "ether 2 1"
- "ether 2 2"
- "ether 2 3"
vlan_id: "2"
vlan_name: "lan2"
- interfaces:
- "pseudo-ether 1"
vlan_id: "501"
vlan_name: "wwan"
- interfaces:
- "ether 2 1"
vlan_id: "1005"
vlan_name: "v1005"
テスト
前項のYAMLファイルと同様にpoetry shell
で仮想環境に入った上で下記コマンドを実行します。
invoke tests
上記コマンドでは全項目が実行されますが、下記のコマンドで特定のテストのみを実施可能です。
bandit : Run bandit to validate basic static code security analysis.
black : Run black to check that Python files adhere to its style standards.
coverage : Run the coverage report against pytest.
flake8 : Run flake8 to check that Python files adhere to its style standards.
mypy : Run mypy to validate typing-hints.
pylint : Run pylint code analysis.
pydocstyle : Run pydocstyle to validate docstring formatting adheres to NTC defined standards.
pytest : Run pytest for the specified name and Python version.
tests : Run all tests for the specified name and Python version.
yamllint : Run yamllint to validate formatting adheres to NTC defined YAML standards.
結果に問題なければOKです。
PRを出す
プルリクを出して承認されるのを待ちましょう。新規テンプレートの場合は1テンプレートごとにPRを出してくださいとのことです。
テンプレート作成のポイント
私がPRで指摘された点をメインにポイントをまとめました。
1.空白の読み込みは\s+
コマンドの出力結果の空白を読み込む場合は長さに関わらず\s+
を使用しましょう。
スペース1文字分しか空いていないときでも\s+
がよいようです。
Current-time : Tue Dec 31 21:29:06 2024
Startup-time : Tue Dec 31 11:29:03 2024
System : Si-R G120
Start
^Current-time\s+:\s+${CURRENT_TIME}\s*$$
^Startup-time\s+:\s+${STARTUP_TIME}\s*$$
^System\s+:\s+${SYSTEM}\s*$$
2.正規表現はシンプルに
正規表現はなるべくシンプルにしましょう。例えばcisco_ios_show_ip_route
ではIPアドレスの正規表現が\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}
となっていますが、私が作成したテンプレートでは\S+
を使用するようにレビューを受けました。
3.フィールド名は既存テンプレートの真似をしよう
フィールド名は機種によって差異がありますが、標準化が徐々に進められており、他機種のテンプレートと揃えることが望ましいです。
下記の機器を参考に合わせていくと良いでしょう。
- cisco_ios
- juniper_junos
- arista_eos