ansibleのnetwork-engineロールのcommand_parserの使い方について


ネットワーク機器の非構造な結果テキストをパースできる network-engine ロールの command_parser の使い方について(忘れるので)書いておこうと思います。
Ansibleもくもく会で使われている演習にも使い方が書いてあります。

network-engineロール

パーサードキュメント

パースモジュール

現在、network-engineロールで使えるモジュールは以下の3つです。

  • command_parser
    • YAMLでパース用テンプレートを書いて、それを元にテキストをパースします
    • ここでは、これを使います
  • textfsm_parser
    • Google TextFSM形式でパース用テンプレートを作成して、それを元にテキストをパースします
  • net_facts
    • ネットワーク機器から基本的なファクト機能を収集します

環境

今回はCSR1000を対象にしてやってみようと思います。

項目 バージョン
Ansible 2.8.3
CSR1000 3.15.0S(ED)
Python 3.6.8

目的

ここでは、コマンド実行で取得したrawテキスト結果を元にレポートを作成してみようと思います。
レポートを作るまでの各処理を一つずつ説明していこうと思います。

全体の処理について

ここでの全体の処理は以下のようになっています。

  • SSHで接続した対象機器上でコマンドを実行
  • 取得した値をregisterで変数に格納
  • テンプレート用パースに上で取得した結果を渡す
  • パース処理が走る
  • パース結果を基にレポートを生成する

ロールのインストール

ansible-galaxy コマンドを実行して network-engine ロールをインストールします。

パースについて

パースは以下のディレクティブ順番で処理します。

  • parser_metadata ではメタ情報を設定します
  • pattern_match ではパースする対象の文字列を取得します
  • pattern_group ではpattern_matchで取得した文字列をループして解析します
  • json_template ではpattern_groupで解析した結果を元に任意のjson形式にします

それでは、一つずつやってみましょう。

inventoryについて

inventoryは以下のようになっています。

対象rawテキストデータ

ここでは show run で取得できたinterfaceを元にレポートを生成します。
そのため、以下の範囲が対象です。

parser_matchについて

まずは、ロールとパース用テンプレートを呼び出すPlaybookを作成します。
Playbookでは shor run コマンドを実行して取得した結果をパースします。

次にパース用のテンプレートファイルを作成します。

parser_metadataオプション

オプション 説明
version バージョンを指定
command 実行したコマンドを指定
network_os ネットワーク機器のOSタイプを指定

pattern_matchオプション

オプション 説明
regex コマンド結果から抜き出したい対象の文字列部分の正規表現を指定
match_all 正規表現にマッチしたものをすべて取得する場合は true
match_greedy 正規表現にマッチした部分ではなく、それ以降も取得する場合は true
match_until 正規表現にマッチした部分で処理を終了させる場合は true
export 呼び出したPlaybookでパース用テンプレート内のregisterに登録した変数を呼び出せるようにする場合は true

今回はinterface情報をパースしたいので正規表現では ^interface を指定しています。

parser_matchの動きを確認する

それでは parser_match の動きを確認してみましょう。
作成したPlaybookを実行してみます。

このように interface にマッチした部分をすべて取得しています。
例えば match_greedyfalse にしてみましょう。

実行してみます。

match_greedyfalse にすると正規表現にマッチする部分のみしか取得できないことがわかります。
これだとinterfaceの情報を取得できないので true にします。

pattern_groupについて

パース用のテンプレートに pattern_group 処理を追加します。

pattern_group では pattern_match で取得した section変数 に格納された値を元に解析の処理をします。

例えばsectionの0番目のデータを見てみます。

interface name の処理で指定している正規表現は interface (.*) です。
(.*) にマッチしたものがregisterの変数に格納されます。
ここでは GigabitEthernet1 が格納されます。
ip address では 192.168.0.68 255.255.255.0 が格納されます。
negotiation では auto が格納されます。
vlanport status は正規表現にマッチしないので null が格納されます。

pattern_groupの動きを確認する

表示する変数を変えるためPlaybookのdebug部分を修正します。

実行してみます。

pattern_groupで作成した interfaces 変数の中身は上のようになりました。
これで、任意のjson形式にできるための構造化ができました。
これを元にレポートを生成してもいいですが、もっと分かりやすい(扱いやすい)形にしてみようと思います。

json_templateについて

パース用のテンプレートに json_template 処理を追加します。

json_templateオプション

オプション 説明
key key名を指定
value keyに紐付ける値を指定
object 辞書をネストする場合は指定
export_as 呼び出したPlaybook側に戻す型を指定

json_template では pattern_group で作成した interfaces変数 を元に任意のjson構造を作成できます。
上のように key value 型で指定します。
辞書がネストする時は object を使います。

json_templateの動きを確認する

表示する変数を変えるためPlaybookのdebug部分を修正します。

実行してみます。

任意のjson構造が作成できました 🙂
これを元にレポートを生成してみようと思います。

レポートを作る

まずは、レポート用のテンプレート(j2)を作成します。

レポート用のテンプレートは以下のようになっています。

次にPlaybookへtemplateモジュール処理を追加します。

これを実行してみます。

report.yml が作成されているので中身を確認してみます。

これで、YAMLのレポートが作成できました 🙂
このように非構造データをパースし任意のjson構造へ変換することができます。
その後は、templateモジュールを使って棚卸または現状把握用のレポートを生成したり取得したデータを元に設定変更をする処理を書いたりすることができて便利ですね 🙂

みんなでハッピーオートメーション!

追記

今回作成したファイルをGitHubに保存しました。

Leave a Reply

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください