Junos PyEZ を使用して Junos デバイスで RPC を実行する
Junos PyEZ を使用して、Junos デバイス上でリモート プロシージャ コール(RPC)をオンデマンドで実行できます。クラスのインスタンスを作成した後、インスタンスのDevice
Device
プロパティとして RPC を実行できます。CLI で実行できるのと同じ操作コマンドの大半は、Junos PyEZ を使用して実行できます。
Junos XML APIは、Junos OS設定ステートメントと運用モードコマンドのXML表現です。Junos OS 設定階層のすべてのステートメントと、CLI 運用モードで発行するコマンドの多くに対応する XML を定義します。Junos XML 対応の各運用モード コマンドは、リクエストタグ要素と、必要に応じて応答タグ要素にマッピングされます。リクエストタグは、NETCONFまたはJunos XMLプロトコルセッション内のRPCで使用され、Junosデバイスから情報を要求します。サーバーは、応答タグ要素内で囲まれた Junos XML 要素を使用して応答を返します。
Junos PyEZ を使用して RPC を実行する場合、リクエスト タグ名をメソッド名にマップします。このトピックでは、CLI コマンドを Junos PyEZ RPC にマッピングする方法、Junos PyEZ を使用した RPC の実行方法、RPC リプレイで返されるデータをカスタマイズする方法について概説します。
Junos OS コマンドを Junos PyEZ RPC にマッピングする
Junos XML に対応するすべての操作コマンドが 、Junos XML API Explorer に表示されます。また、CLI または Junos PyEZ を使用して Junos XML に対応する操作モード コマンドの Junos XML リクエスト タグ要素を表示することもできます。リクエストタグを取得すると、Junos PyEZ RPCメソッド名にマップできます。
CLI でコマンドの Junos XML リクエスト タグを表示するには、 コマンドの後に | display xml rpc
オプションを含めます。以下の例では、 コマンドのリクエストタグを show route
表示しています。
user@router> show route | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R1/junos"> <rpc> <get-route-information> </get-route-information> </rpc> </rpc-reply>
また、Junos PyEZ を使用して、コマンドの Junos XML リクエスト タグを表示することもできます。要求タグを表示するには、インスタンス メソッドをDevice
呼び出し、コマンド文字列と format='text'
を引数として含display_xml_rpc()
めます。例えば:
from jnpr.junos import Device with Device(host='router.example.com') as dev: print (dev.display_xml_rpc('show route', format='text'))
プログラムを実行すると、 コマンドのリクエストタグが show route
返されます。
<get-route-information> </get-route-information>
操作コマンドのリクエストタグを Junos PyEZ RPC メソッド名にマッピングできます。RPCメソッド名を導き出すには、リクエストタグ内のハイフンをアンダースコア(_)に置き換え、外側の山括弧を削除します。たとえば、リクエストタグは <get-route-information>
メソッド名にマッピングされます get_route_information()
。
デバイス インスタンスのプロパティとして RPC を実行する
の Device
各インスタンスには、 rpc
Junos XML APIを介して利用可能なRPCを実行できるプロパティがあります。Junos PyEZ アプリケーションでは、デバイスとの接続を確立した後、次の例に示すように、デバイス インスタンスにプロパティと RPC メソッド名を rpc
付加して RPC を実行できます。
from jnpr.junos import Device from lxml import etree with Device(host='dc1a.example.com') as dev: #invoke the RPC equivalent to "show version" sw = dev.rpc.get_software_information() print(etree.tostring(sw, encoding='unicode'))
戻り値は、タグの下 <rpc-reply>
の最初の要素から始まる XML オブジェクトです。この場合、RPC は get_software_information()
要素を <software-information>
返します。
<software-information> <host-name>dc1a</host-name> ... </software-information>
Junos OS コマンドは、値を持たない固定形式オプションを持つことができます。たとえば、 コマンドに相当する show interfaces terse
Junos XMLは、空の要素であることを terse
示します。
user@router> show interfaces terse | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <terse/> </get-interface-information> </rpc> </rpc-reply>
RPC を実行し、値を受け取らないコマンド オプションを含める場合は、RPC メソッドの引数リストに オプションを追加し、オプション名内のダッシュ線をアンダースコアに変更し、これを True に設定します。次のコードは、Junos PyEZ RPC と同等のコマンドを show interfaces terse
実行します。
rsp = dev.rpc.get_interface_information(terse=True)
Junos OS コマンドには、値を必要とするオプションもあります。たとえば、次の出力では、 interface-name
要素には、情報を返すインターフェイスの名前である値が必要です。
user@router> show interfaces ge-0/0/0 | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/14.1R1/junos"> <rpc> <get-interface-information> <interface-name>ge-0/0/0</interface-name> </get-interface-information> </rpc> </rpc-reply>
RPC を実行し、値を必要とするコマンド オプションを含めるには、RPC メソッドの引数リストに オプションを追加し、オプション名のダッシュをアンダースコアに変更し、適切な値に等しく設定します。次の例では、Junos PyEZ RPC と同等のコマンドを show interfaces ge-0/0/0
実行します。
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0')
RPC 出力の形式を指定する
デフォルトでは、RPC の戻り値は、 タグの下<rpc-reply>
の最初の要素から始まる XML オブジェクトです。RPC メソッドの最初の引数として または {'format':'json'}
辞書のいずれかを{'format':'text'}
含めることで、テキストまたは JavaScript Object Notation(JSON)形式で RPC 出力を返することもできます。
Junos OS リリース 14.2R1 以降では、JSON 形式の RPC 出力がサポートされています。
次の例では、RPC のget_software_information()
出力がテキスト形式で返されます。これは、RPC 出力が要素内<output>
で囲まれている点を除き、CLI の コマンドに対show version
して発行された出力と同じです。
from jnpr.junos import Device from lxml import etree with Device(host='router1.example.com') as dev: sw_info_text = dev.rpc.get_software_information({'format':'text'}) print(etree.tostring(sw_info_text))
user@server:~$ python3 junos-pyez-rpc-text-format.py <output> Hostname: router1 Model: mx104 Junos: 18.3R1.9 JUNOS Base OS boot [18.3R1.9] JUNOS Base OS Software Suite [18.3R1.9] JUNOS Crypto Software Suite [18.3R1.9] JUNOS Packet Forwarding Engine Support (TRIO) [18.3R1.9] JUNOS Web Management [18.3R1.9] JUNOS Online Documentation [18.3R1.9] JUNOS SDN Software Suite [18.3R1.9] JUNOS Services Application Level Gateways [18.3R1.9] JUNOS Services COS [18.3R1.9] JUNOS Services Jflow Container package [18.3R1.9] JUNOS Services Stateful Firewall [18.3R1.9] JUNOS Services NAT [18.3R1.9] JUNOS Services RPM [18.3R1.9] JUNOS Services Captive Portal and Content Delivery Container package [18.3R1.9] JUNOS Macsec Software Suite [18.3R1.9] JUNOS Services Crypto [18.3R1.9] JUNOS Services IPSec [18.3R1.9] JUNOS DP Crypto Software Software Suite [18.3R1.9] JUNOS py-base-powerpc [18.3R1.9] JUNOS py-extensions-powerpc [18.3R1.9] JUNOS jsd [powerpc-18.3R1.9-jet-1] JUNOS Kernel Software Suite [18.3R1.9] JUNOS Routing Software Suite [18.3R1.9] <output>
次の例では、RPC の出力を get_software_information()
JSON 形式で返します。
from jnpr.junos import Device from pprint import pprint with Device(host='router1.example.com') as dev: sw_info_json = dev.rpc.get_software_information({'format':'json'}) pprint(sw_info_json)
user@server:~$ python3 junos-pyez-rpc-json-format.py {u'software-information': [{u'host-name': [{u'data': u'router1'}], u'junos-version': [{u'data': u'18.3R1.9'}], u'package-information': [{u'comment': [{u'data': u'JUNOS Base OS boot [18.3R1.9]'}], u'name': [{u'data': u'junos'}]}, {u'comment': [{u'data': u'JUNOS Base OS Software Suite [18.3R1.9]'}], u'name': [{u'data': u'jbase'}]}, ...
返すデータのスコープを指定する
Junos PyEZ を使用して RPC を実行し、Junos デバイスから運用情報を取得できます。XML 出力を要求すると、特定の要素のみを返すために応答をフィルター処理できます。出力のフィルタリングは、広範囲の運用出力がある場合に有益ですが、必要なのはデータのサブセットのみです。
RPC 応答をフィルタリングして特定のタグのみを返す場合は、RPC メソッドの filter_xml
引数を含めます。このパラメータは filter_xml
、返す要素を選択するサブツリーフィルターを含む文字列を取得します。サブツリー フィルターは、選択基準に一致するデータを返します。
次のJunos PyEZの例は、RPCを<get-interface-information>
実行し、出力をフィルタリングして、応答内の各<physical-interface>
要素の要素だけを<name>
取得します。
from jnpr.junos import Device from lxml import etree with Device(host='router.example.com', use_filter=True) as dev: filter = '<interface-information><physical-interface><name/></physical-interface></interface-information>' result = dev.rpc.get_interface_information(filter_xml=filter) print (etree.tostring(result, encoding='unicode'))
スクリプトを実行すると、各物理インターフェイスの名前要素が表示されます。
user@server:~$ python3 junos-pyez-get-interface-names.py <interface-information style="normal"><physical-interface><name> lc-0/0/0 </name></physical-interface><physical-interface><name> pfe-0/0/0 </name></physical-interface><physical-interface><name> pfh-0/0/0 </name></physical-interface><physical-interface><name> xe-0/0/0 </name></physical-interface><physical-interface><name> xe-0/1/0 </name></physical-interface><physical-interface><name> ge-1/0/0 </name></physical-interface> ... </interface-information>
RPC タイムアウトの指定
RPC の実行時間は、RPC とデバイスによって大きく異なります。デフォルトでは、NETCONF RPC は 30 秒後にタイムアウトします。RPC の実行時に引数を dev_timeout=seconds
含めることで、タイムアウト値を拡張して、RPC の実行中 dev_timeout
に RPC がタイムアウトしないようにすることができます。は、その 1 つの RPC 操作に対してのみデバイスのタイムアウトを調整します。
dev.rpc.get_route_information(table='inet.0', dev_timeout=55)
XML RPC 返信を正規化する
RPC を実行すると、RPC の返信には、改行でラップされたデータや、その他の余分な空白を含むデータを含めることができます。不要な空白スペースは、XMLを解析し、テキストベースの検索を使用して情報を見つけるのを難しくする可能性があります。RPCの返信を正規化して、先頭と末尾の空白をすべて取り除き、内部空白文字のシーケンスを1つのスペースに置き換えることができます。
表 1 は 、デフォルトの RPC 応答を正規化されたバージョンと比較しています。デフォルトの RPC 応答には、正規化された応答に存在しない多くの改行が含まれます。
デフォルト RPC リプライ |
正規化された RPC 返信 |
---|---|
<interface-information style="terse"> <logical-interface> <name>\nge-0/0/0.0\n</name> <admin-status>\nup\n</admin-status> <oper-status>\nup\n</oper-status> <filter-information>\n</filter-information> <address-family> <address-family-name>\ninet\n</address-family-name> <interface-address> <ifa-local emit="emit">\n198.51.100.1/24\n</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
<interface-information style="terse"> <logical-interface> <name>ge-0/0/0.0</name> <admin-status>up</admin-status> <oper-status>up</oper-status> <filter-information/> <address-family> <address-family-name>inet</address-family-name> <interface-address> <ifa-local emit="emit">198.51.100.1/24</ifa-local> </interface-address> </address-family> </logical-interface> </interface-information> |
デバイスとのセッション期間中の正規化を有効にしたり、RPCの実行時に個々のRPC返信を正規化することもできます。デバイスセッション全体の正規化を有効にするには、デバイスインスタンスの作成時または メソッドを使用してデバイスに接続する際に、引数リストにをopen()
含めますnormalize=True
。
dev = Device(host='router1.example.com', user='root', normalize=True) # or dev.open(normalize=True)
個々の RPC の返信を正規化するには、その RPC メソッドの引数リストにを含めます normalize=True
。
dev.rpc.rpc_method(normalize=True)
例えば:
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True)
RPCの返信を正規化しない場合、特定のノードまたは値を参照するXPath式を使用する場合は、空白を考慮する必要があります。以下の例では、論理インターフェイスのIPv4アドレスを選択しています。XPath 式では、検索が成功するためには、ファミリーを指定する inet
述部が追加の空白を考慮する必要があります。結果の値には、先頭と末尾の改行が含まれます。
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True) print (rsp.xpath('.// \ address-family[normalize-space(address-family-name)="inet"]/ \ interface-address/ifa-local')[0].text)
'\n198.51.100.1/24\n'
RPCの返信を正規化すると、先頭と末尾の空白が削除され、テキストベースの検索がはるかに簡単になります。
rsp = dev.rpc.get_interface_information(interface_name='ge-0/0/0.0', terse=True, normalize=True) print (rsp.xpath('.//address-family[address-family-name="inet"]/ \ interface-address/ifa-local')[0].text)
'198.51.100.1/24'