前回PyEzの環境構築ができたため、今回は実際にJUNOSの情報取得を試してみる。
PyEzを使った情報取得方法はいくつかあるが、今回はこの三つを試してみました。
- 事前に定義されている簡単に基本的な情報を取得できるfactsの活用
- YAMLファイルで定義された内容を取得できるTable and Viewの活用
- RPC(remote procedure calls)によるJUNOS showコマンドと同等の確認
#1.JUNOS情報取得(facts)
まずは、非常にシンプルだが、PyEzのHello worldとして、サーバーからJUNOSにコネクションを張り、factsにより基本的な情報(hostname,version情報など)を取得してみる。
factsは、NETCONFセッション確立時にJUNOSから収集した基本的な情報を表示する。
概要はTech Libraryに動作サンプルの動画もあるが、詳細はGitHubで確認可能。
#JUNOSと接続するためにDeviceモジュールをインポート
>>> From juniper. Junos import Device
#デバイス情報を定義
>>> dev=Device(host='10.0.0.243', user="xxx", password="xxx", port='22')
#netconf over sshでJUNOSに接続
>>> Dev. open ()
Device(1.1.1.1)
#factsにより基本情報表示
>>> print dev.facts
{'domain': None, 'hostname': 'vSRX-1', 'ifd_style': 'CLASSIC', 'version_info': junos.version_info(major=(15, 1), type=X, minor=(49, 'D', 50), build=3), '2RE': False, 'serial number': 'xxxxx', 'fqdn': 'vSRX-1', 'switch_style': 'NONE', 'version': '15.1X49-xxx', 'HOME': '/var/home/vsrx', 'srx_cluster': False, 'model': 'VSRX', 'RE0': {'status': 'Testing', 'last_reboot_reason': '0x10: Misc hardware reason ', 'model': 'VSRX RE', 'up_time': '44 minutes'}, 'vc_capable': False, 'personality': 'UNKNOWN'}
#factsによりversion情報だけ表示
>>> dev.facts['version']
'15.1X49-xxx'
>>> dev.facts['hostname']
'vSRX-1‘
dev.close()
>>> quit()
factsを使ってOSのバージョン情報を取得してテキストに書き出すサンプル
from jnpr.junos import Device
from datetime import datetime
mydeviceslist=["1.1.1.1"]
f=open("my_devices_inventory.txt", "a")
f.write(str(datetime.now()) + '\n')
for item in mydeviceslist:
dev=Device(host=item, user="xxx", password="xxx",port='22')
dev.open()
dev.close()
print ("the device "+ dev.facts["hostname"]+ " is a " + dev.facts['model
'] + " running " + dev.facts["version"])
f.write ( "the device "+ dev.facts["hostname"]+ " is a " + dev.facts['mo
del'] + " running " + dev.facts["version"] + "\n")
f.close()
実行結果
$ python print_facts.py
the device vSRX-1 is a VSRX running 15.1X49-xxx
[ec2-user@ip-10-0-0-47 facts]$ more my_devices_inventory.txt
2016-08-22 08:01:29.396263
the device vSRX_AWS-1 is a VSRX running 15.1X49-xxx
#2.JUNOS情報取得(Table and view)
jnpr.junos.opモジュールを使い、YAMLで定義されたTable and Viewにより各情報の取得ができる。
現在のopモジュールとしては、ドキュメントにあるようにarp, interface情報など基本的な情報が取得可能。
例として、ArpTableメソッドを使い、arp情報を取得してみる。
>>> from jnpr.junos.op.arp import ArpTable
>>> arp1=ArpTable(dev)
>>> arp1.get()
ArpTable:10.0.0.243: 3 items
#keyの一覧取得
>>> arp1.keys()
['0a:de:e9:03:15:3f', '0a:ca:89:ec:9a:51', '0a:93:06:42:03:c5']
#valuesの一覧取得
>>> arp1.values()
[[('interface_name', 'fxp0.0'), ('ip_address', '10.0.0.1'), ('mac_address', '0a:de:e9:03:15:3f')], [('interface_name', 'fxp0.0'), ('ip_address', '10.0.0.47'), ('mac_address', '0a:ca:89:ec:9a:51')], [('interface_name', 'ge-0/0/0.0'), ('ip_address', '10.0.1.1'), ('mac_address', '0a:93:06:42:03:c5')]]]
RouteTableメソッドを利用して、ルーティング情報とデフォルトゲートウェイのテーブル情報を表示するサンプル
from jnpr.junos import Device
from jnpr.junos.op.routes import RouteTable
dev = Device(host='10.0.0.243', user='xxx', password='xxx', port='22', gathe
r_facts=False)
dev.open()
tbl = RouteTable(dev)
tbl.get()
#get values and keys
for key, value in tbl.items():
print "key:%s,\t value:%s" %(key, value)
##print only GW information
print '##this is default gateway'
gw = RouteTable(dev)
gw.get('0.0.0.0')
print gw
for item in gw:
print 'protocol:', item.protocol
print 'age:', item.age
print 'via:', item.via
print
dev.close()
実行結果
key:0.0.0.0/0, value:[('nexthop', '10.0.0.1'), ('age', 177947), ('via', 'fxp0.0'), ('protocol', 'Static')]
key:10.0.0.0/24, value:[('nexthop', None), ('age', 177947), ('via', 'fxp0.0'), ('protocol', 'Direct')]
key:10.0.0.243/32, value:[('nexthop', None), ('age', 181163), ('via', 'fxp0.0'), ('protocol', 'Local')]
key:10.0.1.0/24, value:[('nexthop', None), ('age', 181145), ('via', 'ge-0/0/0.0'), ('protocol', 'Direct')]
key:10.0.1.68/32, value:[('nexthop', None), ('age', 181146), ('via', 'ge-0/0/0.0'), ('protocol', 'Local')]
key:10.0.2.98/32, value:[('nexthop', None), ('age', 181144), ('via', 'ge-0/0/1.0'), ('protocol', 'Direct')]
key:10.0.3.85/32, value:[('nexthop', None), ('age', 181144), ('via', 'ge-0/0/2.0'), ('protocol', 'Direct')]
key:192.168.0.1/32, value:[('nexthop', None), ('age', 181162), ('via', 'lo0.0'), ('protocol', 'Direct')]
##this is default gateway
RouteTable:10.0.0.243: 1 items
protocol: Static
age: 177947
via: fxp0.0
YAMLファイルを自分で定義して、Table and Viewを取得することもできる。
Gitに落ちてたサンプルとして、例えばこんな感じ。
#3.JUNOS情報取得(RPC、showコマンド)
最後に、RPCを使いCLIのshowコマンドと同等の情報を取得してみる。
・showコマンドとRPCのマッピング
JUNOS XML APIは、JUNOSのコンフィグやオペレーションモードのコマンドをXMLで表したものだが、
RPCでリクエストすることで、XMLのレスポンスを得ることができる。
PyEzでは、RPCを実行することになるが、CLIのコマンドとRPCは、マッピングできるため、使いたいCLIをRPCとして使うことになる。
そのためには、どのCLIがどのRPCなのかを確認する必要があるが、方法として、2つ紹介する。
- JUNOSの実機でshowコマンドで確認
使いたいshowコマンドのあとに| display xml rpcで確認する。例えばshow interfaceの場合、
> show interfaces | display xml rpc
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1X49/junos">
<rpc>
<get-interface-information>
</get-interface-information>
</rpc>
<cli>
<banner></banner>
</cli>
</rpc-reply>
2.PyEzのdisplay_xml_rpc()メソッドで確認
dev.open()でJUNOSと接続後、dev.display_xml_rpcメソッドで使用したいshowコマンドを指定し確認。
>>> print dev.display_xml_rpc('show interface', format='text')
<get-interface-information>
</get-interface-information>
>>>
これらの確認により、show interfaceは、<get-route-information>というタグだとわかる。
次に、タグからRPCに変換する必要があるが、ハイフン( - )をアンダースコア( _ )に変え、山括弧を排除する。
すなわち、<get-interface-information>の場合、RPCは、get_interface_information() になる。
あとはこのRPCメソッドを使えばいい。
尚、オプションを指定しない場合、XMLで返ってくるため、lxml.etreeライブラリもインポートし、整形して表示するためにetree.tostring()を使う。
・show interfaceを確認するサンプル
from jnpr.junos import Device
from lxml import etree
dev = Device(xxxx,xxx,xxx,xx)
dev.open()
int=dev.rpc.get_interface_information()
print(etree.tostring(int))
・showコマンドオプション利用(値なし)
尚、showコマンドのオプションで、値を使用しないものの場合、RPCメソッドのパラメータで=Trueとすれば確認できる。
例えば、show interface terseを確認するサンプル
dev.open()
int=dev.rpc.get_interface_information(terse=True)
print(etree.tostring(int))
・showコマンドオプション利用(値あり)
showコマンドのオプションで値を利用する場合は、オプションのXMLを同じようにRPCメソッドに変換し、イコールでオプション指定
例えばshow interfaceのinterfaceを指定する場合のタグは、<interface-name> だとわかる。
> show interfaces ge-0/0/0 | display xml rpc
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1X49/junos">
<rpc>
<get-interface-information>
<interface-name>ge-0/0/0</interface-name>
</get-interface-information>
</rpc>
<cli>
よってRPCとしては、interface_nameとなるので、以下のように指定する。
>>> int=dev.rpc.get_interface_information(interface_name='ge-0/0/0')
>>> print(etree.tostring(int))
また、dev.rpc.rpc_method(normalize=True)とすると、返信されたXMLをノーマライズすることもできる。また、返信をXMLでない方法で表示させるのもできそう。
#4.まとめ
だらだらとメモのように書きましたが、
とりあえず、PyEzを使っていくつかの方法で情報取得を試してみました。
次回は設定変更をしてみようと思います。