昨日寝ぼけて、pyatsのシナリオを書こうとしていたフォルダをrm -rf
しちゃいました。というわけでtestbed.yamlから作り直ししたのでその作業記録です。
pyatsのインストール
ちょっと前にやっていたので、忘れてしまいました。historyを辿ると、
python3 -m pip install genie 'pyats[full]'
で何も考えず多分入れたと思います。
公式ドキュメントによるとvenvの利用が推奨らしいです。
$ mkdir pyats
$ cd pyats
$ python3 -m venv .
$ source bin/activate .
(pyats)$
pyATS/Genie: インストールとアップグレードのお話によると、
pip install pyats[full] rest.connector yang.connector
がおすすめのようです。
pyatsのtestbed.yamlの設定
testbed.yaml配下のように作りました。ip:
に続くIPアドレスは皆さんの環境に合わせて適当(適切)に書いてください。
credentials以下のusernameとpasswordはSONiCの標準のままです。環境に合わせて適当(適切)に書いてください。
osは適切なものがなくlinuxにしています。
testbed:
name: sonic-testbed
devices:
sonic-vs1:
os: linux
connections:
ssh:
protocol: ssh
ip: 任意
credentials:
default:
username: admin
password: YourPaSsWoRd
pyatsの内部で動く接続用のlibraryであるuniconの公式ドキュメントのSupported Platformsによると、osのlinuxの配下に、platformがないのでplatformは空欄にしています。
但しpyats validate testbed
をするとWarningを言われます。ですが問題なく動きます
pyats validate testbed testbed.yaml
出力結果:
Loading testbed file: testbed.yaml
--------------------------------------------------------------------------------
Testbed Name:
sonic-testbed
Testbed Devices:
.
`-- sonic-vs1 [linux]
YAML Lint Messages
------------------
Warning Messages
----------------
- Device 'sonic-vs1' missing 'platform' definition
- Device 'sonic-vs1' has no interface definitions
私のようにconnections
をconnection
とsを抜かして動かないと時間を溶かしたりとか、
credentials
をcredential
とsを抜かして動かないと時間を溶かしたりとかをpyats validate testbed
でエラーを出してくれるので事前にやりましょう。
connections
をconnection
と書き間違えている場合。“connections"のキーワードがないと警告してくれる。
Loading testbed file: testbed.yaml
--------------------------------------------------------------------------------
YAML Lint Messages
------------------
Errors
------
- Missing keys:
"connections" parent: [devices.sonic-vs1] (testbed.yaml line:9 column:3)
credentials
をcredential
と書き間違えている場合。“credentials"のキーワードがないと警告してくれる。
Loading testbed file: testbed.yaml
--------------------------------------------------------------------------------
YAML Lint Messages
------------------
Errors
------
- ['devices', 'sonic-vs1']: Unsupported keys:
"credential" (testbed.yaml line:15 column:5)
でもcredentials
以下のdefault
をdefualt
とu
とa
を入れ替えて書いても警告してくれません。文法的には正しいからでしょう。おかげで指定した通りadmin/YourPaSsWoRd (SONiCのデフォルトのusernameとpassword) でログインされず、何故?と時間を溶かしました。
genie shellを使った接続
さて、正しいtestbed.yaml
が準備できたら、早速接続してみましょう
genie shell --testbed-file testbed.yaml
とすると、
Welcome to pyATS Interactive Shell ================================== Python 3.8.10 (default, Mar 13 2023, 10:26:41)
[GCC 9.4.0]
>>> from pyats.topology.loader import load
>>> testbed = load('testbed.yaml') -------------------------------------------------------------------------------
>>>
こんな出力結果が帰ってくると思いますのでプロンプト(>>>
)に
testbed.devices['sonic-vs1'].connect()
とデバイス名を指定して、connect()すると、
2023-04-09 11:54:24,824: %UNICON-INFO: +++ sonic-vs1 logfile /tmp/sonic-vs1-cli-20230409T115424823.log +++
2023-04-09 11:54:24,825: %UNICON-INFO: +++ Unicon plugin linux (unicon.plugins.linux) +++
2023-04-09 11:54:24,829: %UNICON-INFO: +++ connection to spawn: ssh -l admin 192.168.255.3, id: 140480106366384 +++
2023-04-09 11:54:24,829: %UNICON-INFO: connection to sonic-vs1
admin@192.168.255.3's password:
Linux sonic 5.10.0-18-2-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64
You are on
____ ___ _ _ _ ____
/ ___| / _ \| \ | (_)/ ___|
\___ \| | | | \| | | |
___) | |_| | |\ | | |___
|____/ \___/|_| \_|_|\____|
-- Software for Open Networking in the Cloud --
Unauthorized access and/or use are prohibited.
All access and/or use are subject to monitoring.
Help: https://sonic-net.github.io/SONiC/
Last login: Sat Apr 8 22:55:13 2023 from 192.168.255.2
admin@sonic:~$
2023-04-09 11:54:25,223: %UNICON-INFO: +++ initializing handle +++
"\radmin@192.168.255.3's password: \r\nLinux sonic 5.10.0-18-2-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64\r\nYou are on\r\n ____ ___ _ _ _ ____\r\n / ___| / _ \\| \\ | (_)/ ___|\r\n \\___ \\| | | | \\| | | |\r\n ___) | |_| | |\\ | | |___\r\n |____/ \\___/|_| \\_|_|\\____|\r\n\r\n-- Software for Open Networking in the Cloud --\r\n\r\nUnauthorized access and/or use are prohibited.\r\nAll access and/or use are subject to monitoring.\r\n\r\nHelp: https://sonic-net.github.io/SONiC/\r\n\r\nLast login: Sat Apr 8 22:55:13 2023 from 192.168.255.2\r\r\nadmin@sonic:~$ \n"
の様な出力が出てつながります。 一度そのままの出力を出した後にpyatsがparseしようとした結果を出そうとしていますね。
任意のコマンド実行
uniconの公式ドキュメントのSupported Platformsによると、
# Example
# -------
#
# using the above testbed yaml file in pyATS
from pyats.topology import loader
testbed = loader.load('my-testbed.yaml')
device = testbed.devices['csr1000v-1']
device.connect()
device.execute('show version')
と書いてあり、connectで接続、executeで任意コマンドの実行してそうに見えます。というわけで、testbed.devices['デバイス名'].execute('コマンド名')
で、任意のコマンドが実行できるようです。
>>> testbed.devices['sonic-vs1'].execute('show interface status')
こんな感じで応答が返ってきました。
2023-04-09 12:00:05,471: %UNICON-INFO: +++ sonic-vs1 with via 'ssh': executing command 'show interface status' +++
show interface status
Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC
----------- --------------- ------- ----- ----- -------------- ------ ------ ------- ------ ----------
Ethernet0 25,26,27,28 40G 9100 N/A fortyGigE0/0 routed down up N/A N/A
Ethernet4 29,30,31,32 40G 9100 N/A fortyGigE0/4 routed down up N/A N/A
Ethernet8 33,34,35,36 40G 9100 N/A fortyGigE0/8 routed down up N/A N/A
Ethernet12 37,38,39,40 40G 9100 N/A fortyGigE0/12 routed down up N/A N/A
Ethernet16 45,46,47,48 40G 9100 N/A fortyGigE0/16 routed down up N/A N/A
Ethernet20 41,42,43,44 40G 9100 N/A fortyGigE0/20 routed down up N/A N/A
Ethernet24 1,2,3,4 40G 9100 N/A fortyGigE0/24 routed down up N/A N/A
Ethernet28 5,6,7,8 40G 9100 N/A fortyGigE0/28 routed down up N/A N/A
Ethernet32 13,14,15,16 40G 9100 N/A fortyGigE0/32 routed down up N/A N/A
Ethernet36 9,10,11,12 40G 9100 N/A fortyGigE0/36 routed down up N/A N/A
Ethernet40 17,18,19,20 40G 9100 N/A fortyGigE0/40 routed down up N/A N/A
Ethernet44 21,22,23,24 40G 9100 N/A fortyGigE0/44 routed down up N/A N/A
Ethernet48 53,54,55,56 40G 9100 N/A fortyGigE0/48 routed down up N/A N/A
Ethernet52 49,50,51,52 40G 9100 N/A fortyGigE0/52 routed down up N/A N/A
Ethernet56 57,58,59,60 40G 9100 N/A fortyGigE0/56 routed down up N/A N/A
Ethernet60 61,62,63,64 40G 9100 N/A fortyGigE0/60 routed down up N/A N/A
Ethernet64 69,70,71,72 40G 9100 N/A fortyGigE0/64 routed down up N/A N/A
Ethernet68 65,66,67,68 40G 9100 N/A fortyGigE0/68 routed down up N/A N/A
Ethernet72 73,74,75,76 40G 9100 N/A fortyGigE0/72 routed down up N/A N/A
Ethernet76 77,78,79,80 40G 9100 N/A fortyGigE0/76 routed down up N/A N/A
Ethernet80 109,110,111,112 40G 9100 N/A fortyGigE0/80 routed down up N/A N/A
Ethernet84 105,106,107,108 40G 9100 N/A fortyGigE0/84 routed down up N/A N/A
Ethernet88 113,114,115,116 40G 9100 N/A fortyGigE0/88 routed down up N/A N/A
Ethernet92 117,118,119,120 40G 9100 N/A fortyGigE0/92 routed down up N/A N/A
Ethernet96 125,126,127,128 40G 9100 N/A fortyGigE0/96 routed down up N/A N/A
Ethernet100 121,122,123,124 40G 9100 N/A fortyGigE0/100 routed down up N/A N/A
Ethernet104 81,82,83,84 40G 9100 N/A fortyGigE0/104 routed down up N/A N/A
Ethernet108 85,86,87,88 40G 9100 N/A fortyGigE0/108 routed down up N/A N/A
Ethernet112 93,94,95,96 40G 9100 N/A fortyGigE0/112 routed down up N/A N/A
Ethernet116 89,90,91,92 40G 9100 N/A fortyGigE0/116 routed down up N/A N/A
Ethernet120 101,102,103,104 40G 9100 N/A fortyGigE0/120 routed down up N/A N/A
Ethernet124 97,98,99,100 40G 9100 N/A fortyGigE0/124 routed down up N/A N/A
admin@sonic:~$
' Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC\r\n----------- --------------- ------- ----- ----- -------------- ------ ------ ------- ------ ----------\r\n Ethernet0 25,26,27,28 40G 9100 N/A fortyGigE0/0 routed down up N/A N/A\r\n Ethernet4 29,30,31,32 40G 9100 N/A fortyGigE0/4 routed down up N/A N/A\r\n Ethernet8 33,34,35,36 40G 9100 N/A fortyGigE0/8 routed down up N/A N/A\r\n Ethernet12 37,38,39,40 40G 9100 N/A fortyGigE0/12 routed down up N/A N/A\r\n Ethernet16 45,46,47,48 40G 9100 N/A fortyGigE0/16 routed down up N/A N/A\r\n Ethernet20 41,42,43,44 40G 9100 N/A fortyGigE0/20 routed down up N/A N/A\r\n Ethernet24 1,2,3,4 40G 9100 N/A fortyGigE0/24 routed down up N/A N/A\r\n Ethernet28 5,6,7,8 40G 9100 N/A fortyGigE0/28 routed down up N/A N/A\r\n Ethernet32 13,14,15,16 40G 9100 N/A fortyGigE0/32 routed down up N/A N/A\r\n Ethernet36 9,10,11,12 40G 9100 N/A fortyGigE0/36 routed down up N/A N/A\r\n Ethernet40 17,18,19,20 40G 9100 N/A fortyGigE0/40 routed down up N/A N/A\r\n Ethernet44 21,22,23,24 40G 9100 N/A fortyGigE0/44 routed down up N/A N/A\r\n Ethernet48 53,54,55,56 40G 9100 N/A fortyGigE0/48 routed down up N/A N/A\r\n Ethernet52 49,50,51,52 40G 9100 N/A fortyGigE0/52 routed down up N/A N/A\r\n Ethernet56 57,58,59,60 40G 9100 N/A fortyGigE0/56 routed down up N/A N/A\r\n Ethernet60 61,62,63,64 40G 9100 N/A fortyGigE0/60 routed down up N/A N/A\r\n Ethernet64 69,70,71,72 40G 9100 N/A fortyGigE0/64 routed down up N/A N/A\r\n Ethernet68 65,66,67,68 40G 9100 N/A fortyGigE0/68 routed down up N/A N/A\r\n Ethernet72 73,74,75,76 40G 9100 N/A fortyGigE0/72 routed down up N/A N/A\r\n Ethernet76 77,78,79,80 40G 9100 N/A fortyGigE0/76 routed down up N/A N/A\r\n Ethernet80 109,110,111,112 40G 9100 N/A fortyGigE0/80 routed down up N/A N/A\r\n Ethernet84 105,106,107,108 40G 9100 N/A fortyGigE0/84 routed down up N/A N/A\r\n Ethernet88 113,114,115,116 40G 9100 N/A fortyGigE0/88 routed down up N/A N/A\r\n Ethernet92 117,118,119,120 40G 9100 N/A fortyGigE0/92 routed down up N/A N/A\r\n Ethernet96 125,126,127,128 40G 9100 N/A fortyGigE0/96 routed down up N/A N/A\r\nEthernet100 121,122,123,124 40G 9100 N/A fortyGigE0/100 routed down up N/A N/A\r\nEthernet104 81,82,83,84 40G 9100 N/A fortyGigE0/104 routed down up N/A N/A\r\nEthernet108 85,86,87,88 40G 9100 N/A fortyGigE0/108 routed down up N/A N/A\r\nEthernet112 93,94,95,96 40G 9100 N/A fortyGigE0/112 routed down up N/A N/A\r\nEthernet116 89,90,91,92 40G 9100 N/A fortyGigE0/116 routed down up N/A N/A\r\nEthernet120 101,102,103,104 40G 9100 N/A fortyGigE0/120 routed down up N/A N/A\r\nEthernet124 97,98,99,100 40G 9100 N/A fortyGigE0/124 routed down up N/A N/A'
簡易的なparser作りに挑戦
なんだかgenie-parsegenというのを使うと、parserが簡単に作れるらしく、かつテーブル形式だと非常に簡単にParseできそうというのをドキュメント読んだたら気づきました。
ぱっとみheaderの配列だけ作ってあげれば動きそう。というわけで、やってみた。
>>> header = ['Interface', 'Lanes', 'Speed', 'MTU', 'FEC', 'Alias', 'Vlan', 'Oper', 'Admin', 'Type', 'Asym PFC']
>>> import re
>>> from pprint import pprint
>>> from genie.testbed import load
>>> from genie import parsergen
>>> output = testbed.devices['sonic-vs1'].execute('show interface status')
>>> result = parsergen.oper_fill_tabular(device_output=output, device_os='linux', header_fields=header, index=[0])
>>> pprint(result.entries)
出力結果(が長すぎるので先頭のみ抜粋)が以下
{'Ethernet0 25,26,': {'Admin': 'up',
'Alias': 'gE0/0 ro',
'Asym PFC': 'N/A',
'FEC': 'N/A fortyGi',
'Interface': 'Ethernet0 25,26,',
'Lanes': '27,28',
'MTU': '100',
'Oper': 'down',
'Speed': '40G 9',
'Type': 'N/A',
'Vlan': 'uted'},
'Ethernet100 121,122,12': {'Admin': 'up',
'Alias': '0/100 ro',
'Asym PFC': 'N/A',
'FEC': 'N/A fortyGigE',
'Interface': 'Ethernet100 121,122,12',
'Lanes': '3,124',
'MTU': '100',
'Oper': 'down',
'Speed': '40G 9',
'Type': 'N/A',
'Vlan': 'uted'},
これは惜しい。一瞬いい感じに見えましたが、Interfaceの区切り位置が違って一部Laneの情報を含めてしまっています。Speedも一部MTUの出力とっちゃってますね。というわけでちゃんとparserを書かないといけないようです。今日はここまで。