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