ネットワークエンジニア向けのプログラミング:最初のケース

ネットワークでのプログラミングの使用はすでにトレンドになっているため、 「ネットワークエンジニアがプログラミングを必要とする理由」の記事の続きで、特定の実用的な問題を解決する自動化に関する一連の小さなメモを始めます。 このトピックに関する複雑さのハローを打破するために、主にPythonを使用していくつかの例とケースが公開され、より詳細な資料と技術文書へのリンクが提供されます。 このシリーズの紹介記事は以下のとおりです。



拮抗薬に対する最初のいくつかの言葉は、「これは私のためではありません」と急いで言ってはいけません。 データ伝送ネットワークの業界の動向により、「どのように行うか」という問題が背景に押し出され、問題が最前線に効果的に移行しました。 紛れもなく高価ではない運用、これらの同じ傾向により、ネットワークエンジニアはさまざまな自動化ツールを研究する必要があります。 関数へのポインターへのポインターと呼ばれるウイルスに心が「感染」していない人のために、Pythonでこのパスを開始することをお勧めします。 この本は初心者にとって非常にフレンドリーな形式で書かれており、必要な最低限の知識と実践的な経験を得るのに最適です。 章、例、課題の材料は、Pythonの精神と哲学に沿っています。





半分以下の章を読んだ後、Pythonデータ構造を理解し、最初のコードを書くことができるようになります。後半を読むと、HTTPリクエストの送信、CSV形式のデータの操作、JSONドキュメントの解析など、適用された問題の解決におけるPythonの機能のアイデアが得られます。 私は低レベルから高レベルへのスキームによるプログラミングの研究を支持していますが、本を読んだことで、物語自体がプログラミングの基本を理解するよう促していることに気づきました。 あなたがプロのプログラマーではないが、コードの形であなたの考えを定式化する方法を学ぶための文献を探しているだけなら、Pythonをあなたの母国語にしてみてください。



そのため、最初の例は、ジュニパーネットワークスのルーターの動作状態を確認することに専念しています。 参考として、構成されたRSVP LSPのリモート側の相互の肩の存在を確認するタスクを選択しました。 双方向MPLSトランスポートの存在は、さまざまな種類のVPNのトラフィックを転送するための前提条件です。 サービスシグナリングはIP上で十分に機能する可能性があり、データプレーントラフィックにはPEルータ間のシームレスなMPLSパスが必要です。 CLIからLSPパスをテストするには、通常、次のコマンドを使用します



display mpls lsp
      
      





この場合、入力セクションからの各LSPについて、宛先アドレスが最初のLSPの送信元アドレスに等しい出力セクションからのLSPがあることを確認する必要があります。

Pyezでこの問題を解決します。このミニフレームワークには、Pythonコードからルーターと対話するためのクラスとデータ構造のセットが含まれています。 Junos PyEZの機能理解 、およびJunos PyEZのインストール手順の詳細について説明します。



Pyezは、出力形式をXMLに変換するJunosの機能を利用しています。 任意のコマンドにオプションを追加します



 | display xml
      
      





既製のマシンツーマシンインタラクションインターフェイスが得られます。 この機能の詳細については、 XMLおよびJunos OSの概要をご覧ください。



Pyezがルーターからデータを受信するのはこの形式です。未加工のXMLデータを操作することに特別な喜びはないので、ビューとテーブルを使用してこの形式の複雑さから抽象化する方法を説明します。



各Junosコマンドには独自のPyezメソッドがあります。このメソッドの名前を調べるには、 | display xml rpc



| display xml rpc



。 メソッド名はタグ内にあります。この場合、 get-mpls-lsp-information







mpls lspを表示します| xml rpcを表示
 user@host> show mpls lsp | display xml rpc <rpc-reply xmlns:junos="http://xml.juniper.net/junos/15.1R1/j...">; <rpc> <get-mpls-lsp-information> </get-mpls-lsp-information> </rpc> </rpc-reply>
      
      







XML形式の応答を受信することにより、メソッドの出力形式と対応するコマンドに精通するか、 XML API Explorer-Operational Tagsページで確認できますget-mpls-lsp-information



適用されるとget-mpls-lsp-information



ルーターは次のように応答します。



mpls lspを表示します| 表示xml
  <rsvp-session-information> <rsvp-session-data>....</rsvp-session-data> </rsvp-session-information> <rsvp-session-data> <session-type><i>session-type</i></session-type> <count><i>count</i></count> <display-count><i>display-count</i></display-count> <up-count><i>up-count</i></up-count> <down-count><i>down-count</i></down-count> <detours><i>detours</i></detours> <rsvp-session>....</rsvp-session> <mpls-p2mp-lsp>....</mpls-p2mp-lsp> </rsvp-session-data> <rsvp-session> <destination-address><i>destination-address</i></destination-address> <is-detour><i>is-detour</i></is-detour> <source-address><i>source-address</i></source-address> <lsp-state><i>lsp-state</i></lsp-state> <lsp-pktbytes><i>lsp-pktbytes</i></lsp-pktbytes> <bypass-name><i>bypass-name</i></bypass-name> <no-statistics><i>no-statistics</i></no-statistics> <route-count><i>route-count</i></route-count> <rsb-count><i>rsb-count</i></rsb-count> <resv-style><i>resv-style</i></resv-style> <label-in><i>label-in</i></label-in> <label-out><i>label-out</i></label-out> <name><i>name</i></name> <mpls-p2mp-lsp-name><i>mpls-p2mp-lsp-name</i></mpls-p2mp-lsp-name> <p2mp-remerge-state><i>p2mp-remerge-state</i></p2mp-remerge-state> <lsp-description><i>lsp-description</i></lsp-description> <lsp-path-type><i>lsp-path-type</i></lsp-path-type> <mpls-lsp-type><i>mpls-lsp-type</i></mpls-lsp-type> <lsp-aggregation><i>lsp-aggregation</i></lsp-aggregation> <graceful-deletion-triggered><i>graceful-deletion-triggered</i></graceful-deletion-triggered> <source-tna-address><i>source-tna-address</i></source-tna-address> <destination-tna-address><i>destination-tna-address</i></destination-tna-address> <bidirectional><i>bidirectional</i></bidirectional> <associated-bidirectional><i>associated-bidirectional</i></associated-bidirectional> <lsp-associated-lspname><i>lsp-associated-lspname</i></lsp-associated-lspname> <lsp-associated-lspsrc><i>lsp-associated-lspsrc</i></lsp-associated-lspsrc> <upstream-label-in><i>upstream-label-in</i></upstream-label-in> <upstream-label-out><i>upstream-label-out</i></upstream-label-out> <suggested-label-in><i>suggested-label-in</i></suggested-label-in> <suggested-label-out><i>suggested-label-out</i></suggested-label-out> <recovery-label-in><i>recovery-label-in</i></recovery-label-in> <recovery-label-out><i>recovery-label-out</i></recovery-label-out> <psb-lifetime><i>psb-lifetime</i></psb-lifetime> <psb-creation-time><i>psb-creation-time</i></psb-creation-time> <path-mtu><i>path-mtu</i></path-mtu> <path-mtu-in-kernel><i>path-mtu-in-kernel</i></path-mtu-in-kernel> <sender-tspec><i>sender-tspec</i></sender-tspec> <layer2-tspec>....</layer2-tspec> <adspec><i>adspec</i></adspec> <ct-bw><i>ct-bw</i></ct-bw> <lsp-diffserv-info><i>lsp-diffserv-info</i></lsp-diffserv-info> <lsp-id><i>lsp-id</i></lsp-id> <tunnel-id><i>tunnel-id</i></tunnel-id> <proto-id><i>proto-id</i></proto-id> <p2mp-branch-id><i>p2mp-branch-id</i></p2mp-branch-id> <p2mp-subgroup-orig><i>p2mp-subgroup-orig</i></p2mp-subgroup-orig> <self-id><i>self-id</i></self-id> <p2mp-self-id><i>p2mp-self-id</i></p2mp-self-id> <session-id><i>session-id</i></session-id> <is-fastreroute><i>is-fastreroute</i></is-fastreroute> <is-linkprotection><i>is-linkprotection</i></is-linkprotection> <is-nodeprotection><i>is-nodeprotection</i></is-nodeprotection> <is-soft-preemption><i>is-soft-preemption</i></is-soft-preemption> <rsvp-path-status><i>rsvp-path-status</i></rsvp-path-status> <rsvp-lp-backup-route-cnt><i>rsvp-lp-backup-route-cnt</i></rsvp-lp-backup-route-cnt> <rsvp-lp-backup-lsp-cnt><i>rsvp-lp-backup-lsp-cnt</i></rsvp-lp-backup-lsp-cnt> <packet-information>....</packet-information> <explicit-route>....</explicit-route> <record-route>....</record-route> <lsp-attribute-flags>....</lsp-attribute-flags> <lp-history>....</lp-history> <rsvp-telink>....</rsvp-telink> <protection-attribute>....</protection-attribute> <association-attribute>....</association-attribute> <detour>....</detour> <detour-branch>....</detour-branch> <mpls-lsp>....</mpls-lsp> </rsvp-session> <mpls-lsp> <destination-address><i>destination-address</i></destination-address> <source-address><i>source-address</i></source-address> <lsp-state><i>lsp-state</i></lsp-state> <route-count><i>route-count</i></route-count> <active-path><i>active-path</i></active-path> <is-primary><i>is-primary</i></is-primary> <name><i>name</i></name> <bidirectional><i>bidirectional</i></bidirectional> <associated-bidirectional><i>associated-bidirectional</i></associated-bidirectional> <lsp-associated-lspname><i>lsp-associated-lspname</i></lsp-associated-lspname> <lsp-associated-lspsrc><i>lsp-associated-lspsrc</i></lsp-associated-lspsrc> <lsp-description><i>lsp-description</i></lsp-description> <lsp-pktbytes><i>lsp-pktbytes</i></lsp-pktbytes> <lsp-packets><i>lsp-packets</i></lsp-packets> <lsp-bytes><i>lsp-bytes</i></lsp-bytes> <aggregate-lsp-pktbytes><i>aggregate-lsp-pktbytes</i></aggregate-lsp-pktbytes> <no-statistics><i>no-statistics</i></no-statistics> <mpls-p2mp-name><i>mpls-p2mp-name</i></mpls-p2mp-name> <lsp-type><i>lsp-type</i></lsp-type> <lsp-control-status><i>lsp-control-status</i></lsp-control-status> <egress-label-operation><i>egress-label-operation</i></egress-label-operation> <is-fastreroute><i>is-fastreroute</i></is-fastreroute> <is-linkprotection><i>is-linkprotection</i></is-linkprotection> <is-nodeprotection><i>is-nodeprotection</i></is-nodeprotection> <is-inter-domain-path><i>is-inter-domain-path</i></is-inter-domain-path> <load-balance><i>load-balance</i></load-balance> <lsp-diffserv-te-info><i>lsp-diffserv-te-info</i></lsp-diffserv-te-info> <metric><i>metric</i></metric> <revert-timer><i>revert-timer</i></revert-timer> <revert-timer-remain><i>revert-timer-remain</i></revert-timer-remain> <optimize-protection-timer><i>optimize-protection-timer</i></optimize-protection-timer> <admin-groups>....</admin-groups> <admin-groups-extended>....</admin-groups-extended> <mpls-srlg>....</mpls-srlg> <lsp-creation-time><i>lsp-creation-time</i></lsp-creation-time> <lsp-soft-preemption-counter><i>lsp-soft-preemption-counter</i></lsp-soft-preemption-counter> <lsp-soft-preemption-time><i>lsp-soft-preemption-time</i></lsp-soft-preemption-time> <retry-timer><i>retry-timer</i></retry-timer> <retry-limit><i>retry-limit</i></retry-limit> <mpls-lsp-autobandwidth>....</mpls-lsp-autobandwidth> <mpls-lsp-path>....</mpls-lsp-path> <mpls-lsp-attributes>....</mpls-lsp-attributes> </mpls-lsp>
      
      







XMLドキュメントは、子要素またはアトミック値を含む可能性のある要素で構成されます。 たとえば、 <rsvp-session-information> </rsvp-session-information>



要素には子<rsvp-session-data></rsvp-session-data>



要素が含まれ、その中に<rsvp-session>



要素が含まれますこれは、 name



型のアトミック値を持つ要素<mpls-lsp>



です。



この種のネスト構造でサイクルを編成するには、ビューとテーブルを使用します。 このアプローチは、Pythonの動的型付けに依存して、実行時に辞書の配列またはリストを作成します。 <rsvp-session-data>



などの要素に特定の数の<rsvp-session>



サブ要素が含まれる場合、それらのリストを取得します。また、 <destination-address>



などのサブ要素が一意である場合、その値をオブジェクトとして取得します。 テーブルとビューの詳細については、「 Junos PyEZ操作テーブルの 定義」および「操作テーブルの Junos PyEZビューの定義」を参照してください。



サンプルコードのビューとテーブルの形式は、 yml



文字列変数に設定されています。この形式の主要な要素は次のとおりです。



rpc値はテーブルで使用され、 display xml rpc



出力からのメソッド名が含まれています。



アイテムの値はテーブルで使用され、関心のあるXML要素の名前が含まれています。 名前は、XMLドキュメント内のパスの階層に基づいて指定されます。



ビュー値はテーブルで使用され、ビューの説明が含まれています。 ネストされた要素がある場合は、ネストされた説明を作成する必要があります。



fields値はビューで使用され、アトミック要素の名前が含まれています。



ここで、おそらく、Pyezについて知っておく必要のあるすべてが、ルーターのフラットで埋め込みの運用データの反復を整理するために必要です。以下に例を示します。



 import sys import yaml from jnpr.junos.factory.factory_loader import FactoryLoader from jnpr.junos import Device yml = ''' --- MplsSession: rpc: get-mpls-lsp-information item: rsvp-session-data view: MplsSessionView MplsSessionView: fields: type: session-type count: count lsp: _MplsLsp rsvp: _RsvpLsp _RsvpLsp: item: rsvp-session view: _MplsLspView _MplsLsp: item: rsvp-session/mpls-lsp view: _MplsLspView _MplsLspView: fields: dst_addr: destination-address src_addr: source-address state: lsp-state route_count: route-count active_path: active-path name: name ''' globals().update(FactoryLoader().load(yaml.load(yml))) if (len(sys.argv) < 4): print 'Call this script as ' + sys.argv[0] + ' host user password ' sys.exit() try: host = sys.argv[1] user = sys.argv[2] password = sys.argv[3] dev = Device(host=host, user=user, password=password, mode='telnet', port='23') dev.open() except Exception: print 'Cannot connect to ' + host sys.exit() bt = MplsSession(dev).get() dev.close() out='' for s in bt: if (s.type == 'Ingress'): for l in s.lsp: bidir = 0 for ss in bt: if (ss.type == 'Egress'): for r in ss.rsvp: if ( (r.dst_addr == l.src_addr) and (r.src_addr == l.dst_addr) ): bidir = 1 out = 'Remote LSP named ' + r.name if (bidir == 0): print 'Unidirectional LSP named ' + l.name + ' to: ' + l.dst_addr + ' is in ' + l.state + ' state' if (bidir == 1): print 'Bidirectional LSP named ' + l.name + ' to: ' + l.dst_addr + ' is in ' + l.state + ' state' print out print ''
      
      






All Articles