見出し画像

ゼロから始める自動化マスター⑤出力データの抽出について

今日も自動化~と思ってたら・・・なんとデバイス接続用にDevNetsで使っていたpyATSが検索しても出てこない!?

理由は不明ですが、なくなったようです。。。

DevNetsで利用する機器の変更

どうする、この企画はここで終わりなのか・・・まだだ、まだ終わらんよ。
ということで、代わりにCisco Modeling LabのDevNetsを立ち上げましょうw

https://devnetsandbox.cisco.com/RM/Topology


DevNetsのページを立ち上げて、今度はcisco modelingとかで検索すると上の2つが出てくるので左側を選択。
CMLで検索すると右のEnterpriseしか選べない(エンタープライズだからXROS触れない)ので注意。

後はこれまでと同じようにReserveしちゃってください。
ただし、こちらだと4時間しか使えないようです。
pyATSだと8時間予約できたのにーと思いましたが、多少の誤差です。

pyATSと同じマネジメントIPだったので、これまで作ったtestbed.yamlは使いまわせました。

genieによるパースの理解

このgenieですが、マジで便利です。
必用な値のパースがめちゃ簡単にできます。

今回はgenieのパースとさらに、パースした値を簡単に抽出してくれる呪文を見てみましょう。

genieを簡単にテストするためのgenie shell

今回はgenieのパーステストをメインで行いたいのでこれを試す環境を用意しましょう。
genie shellというものを起動すればgenieで利用できるコマンドを簡単に確認できます。
testbedファイルはこれまでに作成したものを使ってください。
また、自身で設定したtestbedファイル内の装置名(下の例はcore-rtr01)で接続してください。(以下の結果は、10.10.20.173の機器へ接続して試しています。)
※注意:
venvの環境も忘れず立ち上げといてください。
DevNetsの環境も設定完了後にさらに5-10分ほどかけて内部のXRvたちが起動してることがあるので、自分の端末からtelnet試していけることも確認してください。

genie shell --testbed test1.yaml
xr = testbed.devices["core-rtr01"]
xr.connect()

testbed.devices・・・を毎回記載するのが面倒なので変数xrに代入してます。

showコマンド全体のパース

前回のNote試したパースも以下で簡単に実行できてしまいます。

output = xr.parse("show ospf neighbor")

今回は検証結果比較に使いたい値だけを抽出したいので、変数outputに出力された値を代入してます。

検証結果に必要なデータを抽出するには?

さて、ずらずら出ているshowコマンド結果から必要なデータを取り出すにはどうすればよいのでしょうか。

これもめちゃくちゃ簡単でDqというものを使えばOKです。

output.q.contains_key_value("vrfs", "default" ).get_values("neighbors")
['172.16.252.38', '172.31.252.2', '172.16.252.25', '172.16.252.33']

全くようわからんのだけど、dataの見方は?

今回は以下で値を抽出しました。
①genieのparseによってPythonの辞書型で抽出
②genieのDqにより、上記から必要な値を抜き取り

接続した機器のOSPFネイバーアドレスを確認したかったので、show ospf neighborをまずは確認しました

{'process_name': '1', 'vrfs': {'default': {'neighbors':
          {'172.16.252.38': {'priority': '1', 'state': 'FULL/BDR', 'dead_time': '00: 00: 38', 'address': '172.16.253.3', 'interface': 'GigabitEthernet0/0/0/1', 'up_time': '01: 08: 57'
                }, '172.31.252.2': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 39', 'address': '172.16.253.4', 'interface': 'GigabitEthernet0/0/0/1', 'up_time': '01: 09: 01'
                }, '172.16.252.25': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 34', 'address': '172.16.252.21', 'interface': 'GigabitEthernet0/0/0/2', 'up_time': '01: 08: 52'
                }, '172.16.252.33': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 37', 'address': '172.16.252.29', 'interface': 'GigabitEthernet0/0/0/3', 'up_time': '01: 08: 52'
                }
            }, 'total_neighbor_count': 5
        }
    }
}

1行でぐちゃっと抽出されるのを少し整形したのが上記です。
Pythonの辞書型は「key:Value」の入れ子で値が表示されます。
比べるために見慣れたshowコマンドベースも貼っときます。

Neighbor ID     Pri   State           Dead Time   Address         Interface
172.16.252.38   1     FULL/DR         00:00:34    172.16.252.38   GigabitEthernet0/0/0/0
Neighbor is up for 01:19:49
172.16.252.38   1     FULL/BDR        00:00:39    172.16.253.3    GigabitEthernet0/0/0/1
Neighbor is up for 01:20:03
172.31.252.2    1     FULL/DR         00:00:31    172.16.253.4    GigabitEthernet0/0/0/1
Neighbor is up for 01:20:08
172.16.252.25   1     FULL/DR         00:00:32    172.16.252.21   GigabitEthernet0/0/0/2
Neighbor is up for 01:19:59
172.16.252.33   1     FULL/DR         00:00:37    172.16.252.29   GigabitEthernet0/0/0/3
Neighbor is up for 01:19:59

vrf defaultのみでOSPFを構成してるので、vrfsをKeyとした場合、値はdefaultで表示されるすべてになります。

 'vrfs': {'default': {'neighbors': {'172.16.252.38': {'priority': '1', 'state': 'FULL/BDR', 'dead_time': '00: 00: 38', 'address': '172.16.253.3', 'interface': 'GigabitEthernet0/0/0/1', 'up_time': '01: 08: 57'
                }, '172.31.252.2': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 39', 'address': '172.16.253.4', 'interface': 'GigabitEthernet0/0/0/1', 'up_time': '01: 09: 01'
                }, '172.16.252.25': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 34', 'address': '172.16.252.21', 'interface': 'GigabitEthernet0/0/0/2', 'up_time': '01: 08: 52'
                }, '172.16.252.33': {'priority': '1', 'state': 'FULL/DR', 'dead_time': '00: 00: 37', 'address': '172.16.252.29', 'interface': 'GigabitEthernet0/0/0/3', 'up_time': '01: 08: 52'
                }
            }, 'total_neighbor_count': 5
        }
    }

つまりは、'vrfs'をkeyとした場合は上記全部です。
{}が多すぎてなんかややこしいのですが、show ospf neiと比べた結果と一致するので合ってますよねw

Neighbor ID     Pri   State           Dead Time   Address         Interface
172.16.252.38   1     FULL/DR         00:00:34    172.16.252.38   GigabitEthernet0/0/0/0
Neighbor is up for 01:19:49
172.16.252.38   1     FULL/BDR        00:00:39    172.16.253.3    GigabitEthernet0/0/0/1
Neighbor is up for 01:20:03
172.31.252.2    1     FULL/DR         00:00:31    172.16.253.4    GigabitEthernet0/0/0/1
Neighbor is up for 01:20:08
172.16.252.25   1     FULL/DR         00:00:32    172.16.252.21   GigabitEthernet0/0/0/2
Neighbor is up for 01:19:59
172.16.252.33   1     FULL/DR         00:00:37    172.16.252.29   GigabitEthernet0/0/0/3
Neighbor is up for 01:19:59

{}でくくられたところを細かくみていくと、全部包含されているのがわかります。

さぁ、値を取り出そう

さて、この中から必要な値を出します。
Dq(Data query)というものを使って、定義されてるKeyを数珠つなぎにするようにして簡単に値が取り出せます。
今回は、ospfのNeighborIDを取り出してみましょう。

取り出したいKeyはvrfsの後にあるdefaultですよね。
そして、Valueがneighborsになります。

 'vrfs': {'default': {'neighbors': {'172.16.252.38': 

outputは先ほどパースして抽出した値を入れた変数で、ここに.q.contains_key_valueでKeyとする値を入力そして、最後にget_valuesでValueを入れると~あら不思議NeighborIDが取り出せましたとさw

output.q.contains_key_value("vrfs", "default" ).get_values("neighbors")
['172.16.252.38', '172.31.252.2', '172.16.252.25', '172.16.252.33']

やってみると、拍子抜けるほど簡単でした。

ついでに、IFのGi0/0/0/2だけに関するものにするなら以下

output.q.contains_key_value("interface", "GigabitEthernet0/0/0/1" ).get_values("neighbors")
['172.16.252.38', '172.31.252.2']

key:value形式じゃなくても、検索はいけるようです。
オプションは色々あるみたい。

output.q.contains("GigabitEthernet0/0/0/1").get_values("neighbors")
['172.16.252.38', '172.31.252.2']


気付いてしまったこと・・・

めっちゃつかえるーと思ったんですが、バグも発見してしまいましたTT
show ospf neiやると、5個のネイバー出てくるはずなのに初めの1行目が保存されてなかったw

output.q.contains("vrfs").get_values("neighbors")
['172.16.252.38', '172.31.252.2', '172.16.252.25', '172.16.252.33']
Neighbor ID     Pri   State           Dead Time   Address         Interface
172.16.252.38   1     FULL/DR         00:00:37    172.16.252.38   GigabitEthernet0/0/0/0
    Neighbor is up for 01:48:26
172.16.252.38   1     FULL/BDR        00:00:34    172.16.253.3    GigabitEthernet0/0/0/1
    Neighbor is up for 01:48:40
172.31.252.2    1     FULL/DR         00:00:34    172.16.253.4    GigabitEthernet0/0/0/1
    Neighbor is up for 01:48:45
172.16.252.25   1     FULL/DR         00:00:36    172.16.252.21   GigabitEthernet0/0/0/2
    Neighbor is up for 01:48:36
172.16.252.33   1     FULL/DR         00:00:38    172.16.252.29   GigabitEthernet0/0/0/3
    Neighbor is up for 01:48:36

ずっとgi0/0/0/0で検索して何も出ないからおかしいと思ったんだよ・・・
バグを見つけたらgithub上から連絡してください。

Freeだからこんなことあるよねぇ~というのとpythonのコードは置いてあるので読み込んで自分で直すしかないですね。。。

さて、検証自動化に必要なパース抽出はできるようになったので、次はテスト結果出力してくれるRobotFrameworkと組み合わせてみましょう。

参考資料


この記事が気に入ったらサポートをしてみませんか?