pyATS/Genie: プログラミング不要な Genie CLI でログチェックの効率化/高速化/自動化

(この記事はネットワーク自動化 Advent Calendar 2019 11日目として書いています)

ネットワーク自動化のカレンダーページです。

今回は pyATS/Genie から Genie CLI を紹介します。pyATS/Genie は python でプログラムを書く必要があるんでしょ?python 知らないし敷居が高いなぁ。。そんな人にオススメなのがプログラミング知識不要の Genie CLI です。
(不要とは言っても Genie CLI を使うのに python の環境と pyATS/Genie のインストールは必要ですが、コードを書く必要はありません)

ネットワーク構成

今回は IOSXE(R1_xe)、IOS-XR(R2_xr)、NX-OS(R3_nx)を VIRL 上で起動して使います。

全ルータで OSPF が Area0 で設定されており、接続インタフェースとループバック(10.1.1.1/32, 10.2.2.2/32, 10.3.3.3/32)が OSPF 経路として見える状況です。

R1_xe でのルーティングテーブルは下記になります。10.2.2.2/32 が R2_xr のループバックで 10.3.3.3/32 が R3_nx のループバックになります。

R1_xe#show ip route                                                             
Codes: L - local, C - connected, S - static, R - RIP, M - mobile, B - BGP       
       D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area           
       N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2           
       E1 - OSPF external type 1, E2 - OSPF external type 2                     
       i - IS-IS, su - IS-IS summary, L1 - IS-IS level-1, L2 - IS-IS level-2    
       ia - IS-IS inter area, * - candidate default, U - per-user static route  
       o - ODR, P - periodic downloaded static route, H - NHRP, l - LISP        
       a - application route                                                    
       + - replicated route, % - next hop override, p - overrides from PfR      
                                                                                
Gateway of last resort is not set                                               
                                                                                
      10.0.0.0/32 is subnetted, 3 subnets                                       
C        10.1.1.1 is directly connected, Loopback0                              
O        10.2.2.2 [110/2] via 172.16.12.2, 00:22:05, GigabitEthernet2           
O        10.3.3.3 [110/3] via 172.16.12.2, 00:00:16, GigabitEthernet2           
      172.16.0.0/16 is variably subnetted, 3 subnets, 2 masks                   
C        172.16.12.0/24 is directly connected, GigabitEthernet2                 
L        172.16.12.1/32 is directly connected, GigabitEthernet2                 
O        172.16.23.0/24 [110/2] via 172.16.12.2, 00:22:05, GigabitEthernet2    

genie parse

genie parse は show コマンドを打ってログを保存するコマンドになります。
show command は実際のコマンドと同様のものになります。また省略形は使えません。(sh run とかはできず、show running-config)

下記は ‘show ip route’ を genie parse で実行した結果です。 genie parse コマンドは機器へ show コマンドを入力して python dictionary (構造化データ)を返します。

(pyats)$ genie parse 'show ip route' --testbed-file tb.yaml
  0%|                                                                                                                                           | 0/1 [00:00<?, ?it/s]{
  "vrf": {
    "default": {
      "address_family": {
        "ipv4": {
          "routes": {
            "10.1.1.1/32": {
              "active": true,
              "next_hop": {
                "outgoing_interface": {
                  "Loopback0": {
                    "outgoing_interface": "Loopback0"
                  }
                }
              },
              "route": "10.1.1.1/32",
              "source_protocol": "connected",
              "source_protocol_codes": "C"
            },
(snip)

default では testbed.yaml に記載されている全機器に対して実行されます。例えば、show ip route コマンドは iosxr ではコマンドが違うため、下記のようにパーサーが見つけられなかったとエラーにはなりますが、全機器分の処理は進みます。

  0%|                                                                                                                                           | 0/1 [00:00<?, ?it/s]Issue with the parser show ip route


Traceback (most recent call last):
  File "src/genie/cli/commands/parser.py", line 289, in genie.cli.commands.parser.ParserCommand.parse
  File "src/genie/conf/base/device.py", line 522, in genie.conf.base.device.Device.parse
  File "/Users/cciojisan/.pyenv/versions/3.7.3/envs/pyats/lib/python3.7/site-packages/genie/libs/parser/utils/common.py", line 92, in get_parser
    c=command, l=lookup._tokens)) from None
Exception: Could not find parser for 'show ip route' under ('iosxr', 'iosxrv9k')
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 198.69it/s]

実際にはファイルに出力して記録することが多いため、下記のように –output オプションで出力先のフォルダを指定して実行します。

(pyats)$ genie parse 'show ip route' --testbed-file tb.yaml --output log
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  1.73it/s]
+==============================================================================+
| Genie Parse Summary for R1_xe                                                |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -  Log: log/connection_R1_xe.txt                                            |
|------------------------------------------------------------------------------|
|  Parsed command 'show ip route'                                              |
|  -  Parsed structure: log/R1_xe_show-ip-route_parsed.txt                     |
|  -  Device Console:   log/R1_xe_show-ip-route_console.txt                    |
|------------------------------------------------------------------------------|
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 182.12it/s]
+==============================================================================+
| Genie Parse Summary for R2_xr                                                |
+==============================================================================+
|  Connected to R2_xr                                                          |
|  -  Log: log/connection_R2_xr.txt                                            |
|------------------------------------------------------------------------------|
|  Could not parse 'show ip route'                                             |
|  -  Exception:      log/R2_xr_show-ip-route_exception.txt                    |
|  -  Device Console: log/R2_xr_show-ip-route_console.txt                      |
|------------------------------------------------------------------------------|
(snip)

各機器毎に下記のファイルが作成されます。

<hostname>_<show command>_parsed.txt構造化されたデータ
(正常にパースできた場合のみ)
<hostname>_<show command>_console.txt実際のコンソール出力
<hostname>_<show command>_exception.txtエラー出力
(パースに問題があった場合のみ)

R2_xr で exception ファイルが生成されていますが、これは前述した show コマンドがサポートされていないため、この場合は特に気にする必要はありません。SchemaMissingKeyError などの別のエラーになっている場合はパーサーの問題の可能性があるので、その場合は GitHub の Issues を上げるか pyats-support(at)cisco.com まで上記ファイル(_console.txt と_exception.txt) をメールで送って報告しましょう。もちろんオープンソースなので自分で PR をオープンするという方法もあります。

特定のデバイスのみ、接続方法を指定、複数 show コマンドを指定することで取得の方法を変更することが可能です。

(pyats)$ genie parse 'show ip route' 'show version' --testbed-file tb.yaml --output log --devices R1_xe --via R1_xe:telnet
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:00<00:00,  2.21it/s]
+==============================================================================+
| Genie Parse Summary for R1_xe                                                |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -  Log: log/connection_R1_xe.txt                                            |
|------------------------------------------------------------------------------|
|  Parsed command 'show ip route'                                              |
|  -  Parsed structure: log/R1_xe_show-ip-route_parsed.txt                     |
|  -  Device Console:   log/R1_xe_show-ip-route_console.txt                    |
|------------------------------------------------------------------------------|
|  Parsed command 'show version'                                               |
|  -  Parsed structure: log/R1_xe_show-version_parsed.txt                      |
|  -  Device Console:   log/R1_xe_show-version_console.txt                     |
|------------------------------------------------------------------------------|

また、構造化データは不要でネットワーク機器のコンソール出力だけを保存したいという場合には –raw コマンドがあります。

(pyats)$ genie parse 'show ip route' --testbed-file tb.yaml --output log --devices R1_xe --via R1_xe:telnet --raw
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  3.52it/s]
+==============================================================================+
| Genie Execute Summary for R1_xe                                              |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -  Log: log/connection_R1_xe.txt                                            |
|------------------------------------------------------------------------------|
|  Executed command 'show ip route'                                            |
|  -  Device Console:   log/R1_xe_show-ip-route_console.txt                    |
|------------------------------------------------------------------------------|

genie parse を実行すると下記のエラーが出力されてる場合はデバイスが複数のコネクション設定(telnet/ssh/console)を持っており、どれを使っていいのか分からないためです。

Unicon is not able to identify the connection to be used, Please use the "via" option to specify the connection block to use

この場合の対策としては2つあります。

  1. testbed.yaml に defaults / via オプションを追加する
devices:
  R1_xe:
    (snip)
    connections:
      defaults:  <<< HERE
        via: ssh <<< HERE
      ssh:
        ip: 172.16.1.228
        protocol: ssh
        proxy: jump_host

2. または前述のように devices と via オプションを genie parse コマンドへ渡す

下記では複数機器の場合の例です。

(pyats)# genie parse 'show ip route' 'show version' --testbed-file tb.yaml --output log --devices R1_xe R2_xr --via R1_xe:telnet R2_xr:ssh

また、エラーは出ないものの _parsed.txt (構造化データ) の表示がおかしい、何か抜けているという場合はパーサーがうまく機能してない場合が考えれます。その場合に便利なのが –developer オプションです。

(pyats)$ genie parse 'show ip route' --testbed-file tb.yaml --output log --devices R1_xe --via R1_xe:telnet --developer
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  1.73it/s]
+==============================================================================+
| Genie Parse Summary for R1_xe                                                |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -  Log: log/connection_R1_xe.txt                                            |
|------------------------------------------------------------------------------|
|  Parsed command 'show ip route'                                              |
|  -  Parsed structure: log/R1_xe_show-ip-route_parsed.txt                     |
|  -  Developer console: log/R1_xe_show-ip-route_console_dev.txt               |
|  -  Device Console:   log/R1_xe_show-ip-route_console.txt                    |
|------------------------------------------------------------------------------|

この場合には新たに _console_dev.txt ファイルが生成されます。この中身を見るとパースされた箇所がグリーン表示されるため、どこがパースされてどこがされていないかを確認することができます。パースされていない行には <<<< が付与されます。
※開発者向けの確認を補助するための機能のため、万能でない場合があります。

genie learn

genie learn は Genie Ops モデルに沿った情報取得は行います。こちらが Genie Model のページです。

The Genie (pyATS Library) Feature Browser. Easily find the right Trigger, Verification, Parser, API, or Model.

Genie Ops Ospf モデルだと下記のようにプラットフォーム毎に取得するコマンドが確認できます。左から iosxe, iosxr, nxos の show コマンドリストになっています。

genie learn にも渡せるパラメーターがあるのですが、–devices / –via / –output は genie parse と同じです。

genie learn の後に入力するのは Genie Ops のモデル名になります。モデル名は上のリンクから確認できます。下記は ‘routing’ (ルーティングテーブルの確認) を実行した結果です。

(pyats)$ genie learn 'routing' --testbed-file tb.yaml

Learning '['routing']' on devices '['R1_xe', 'R2_xr', 'R3_nx']'
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:02<00:00,  2.05s/it]
+==============================================================================+
| Genie Learn Summary for device R1_xe                                         |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -   Log: ./connection_R1_xe.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_iosxe_R1_xe_ops.txt                            |
|  -  Device Console: ./routing_iosxe_R1_xe_console.txt                        |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device R2_xr                                         |
+==============================================================================+
|  Connected to R2_xr                                                          |
|  -   Log: ./connection_R2_xr.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_iosxr_R2_xr_ops.txt                            |
|  -  Device Console: ./routing_iosxr_R2_xr_console.txt                        |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device R3_nx                                         |
+==============================================================================+
|  Connected to R3_nx                                                          |
|  -   Log: ./connection_R3_nx.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_nxos_R3_nx_ops.txt                             |
|  -  Device Console: ./routing_nxos_R3_nx_console.txt                         |
|==============================================================================|

genie learn ではデフォルトでファイルを保存します。–output を使用しなかった場合はコマンドを実行した場所に保存されます。

複数の情報を同時に取得したい場合は下記のように列挙することで可能です。(‘routing’ と ‘ospf’ を指定した例)

(pyats)$ genie learn 'routing' 'ospf' --testbed-file tb.yaml

Learning '['routing', 'ospf']' on devices '['R1_xe', 'R2_xr', 'R3_nx']'
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:12<00:00,  6.23s/it]
+==============================================================================+
| Genie Learn Summary for device R1_xe                                         |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -   Log: ./connection_R1_xe.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_iosxe_R1_xe_ops.txt                            |
|  -  Device Console: ./routing_iosxe_R1_xe_console.txt                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxe_R1_xe_ops.txt                               |
|  -  Device Console: ./ospf_iosxe_R1_xe_console.txt                           |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device R2_xr                                         |
+==============================================================================+
|  Connected to R2_xr                                                          |
|  -   Log: ./connection_R2_xr.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_iosxr_R2_xr_ops.txt                            |
|  -  Device Console: ./routing_iosxr_R2_xr_console.txt                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxr_R2_xr_ops.txt                               |
|  -  Device Console: ./ospf_iosxr_R2_xr_console.txt                           |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device R3_nx                                         |
+==============================================================================+
|  Connected to R3_nx                                                          |
|  -   Log: ./connection_R3_nx.txt                                             |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ./routing_nxos_R3_nx_ops.txt                             |
|  -  Device Console: ./routing_nxos_R3_nx_console.txt                         |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_nxos_R3_nx_ops.txt                                |
|  -  Device Console: ./ospf_nxos_R3_nx_console.txt                            |
|==============================================================================|

また上記は 3デバイス から情報を取得していますが、ログ取得は1デバイス毎ではなく並行してログ取得が行われます。何らかの理由で1デバイス毎にしたい場合は –single-process を指定することで可能です。

作成された _ops.txt を見ると上記 Genie Model ページで確認できる Ops Structure に沿った構造化データが確認できます。これは iosxe/iosxr/nxos のいずれからも同じ階層構造になります。同じものではないですが、コンセプトとしては Yang の共通モデルと同じです。

(pyats)$ cat ops/routing_iosxe_R1_xe_ops.txt
{
  "_exclude": [
    "updated"
  ],
  (snip)
  "info": {
    "vrf": {
      "default": {
        "address_family": {
          "ipv4": {
            "routes": {
              "10.1.1.1/32": {
                "active": true,
                "next_hop": {
(snip)

_exlude にはデフォルトで除外されるキーが指定されいます。’updated’ は経路のuptimeのため、常時変動(インクリメント)しており、無視できるものとして指定しています。これは後述の genie diff で使用されます。

genie diff

ここまでで genie parse は show コマンドから構造化データを保存、genie learn は Genie Model に沿った show コマンドから共通化された構造化データを保存するものと確認しました。

取得したファイルを使って genie diff を使うことで差分を簡単に見ることができます。これはネットワーク運用環境下でよくある下記作業に Genie CLI が使えます。

  • 作業前ログ取得 -> genie parse 又は genie learn
  • 実作業
  • 作業後ログ取得 -> genie parse 又は genie learn
  • ログ比較チェック -> genie diff

それでは上記のフローで試してにやってみます。

作業前ログ取得 (genie learn)

genie learn で ‘routing’ を取得し、作業前として ops_before フォルダに保存します。

(pyats)$ genie learn 'routing' --testbed-file tb.yaml --output ops_before

Learning '['routing']' on devices '['R1_xe', 'R2_xr', 'R3_nx', 'jump_host']'
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:02<00:00,  2.05s/it]
+==============================================================================+
| Genie Learn Summary for device R1_xe                                         |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -   Log: ops_before/connection_R1_xe.txt                                    |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ops_before/routing_iosxe_R1_xe_ops.txt                   |
|  -  Device Console: ops_before/routing_iosxe_R1_xe_console.txt               |
|==============================================================================|

実作業

何かしらメンテナンス作業を行い、作業の完了(前と同じ状態になった)したとします。

作業後のログ取得 (genie learn)

作業前と同じく genie learn で ‘routing’ を学習しますが、今回は作業後として ‘ops_after’ フォルダに保存します。

(pyats)$ genie learn 'routing' --testbed-file tb.yaml --output ops_after

Learning '['routing']' on devices '['R1_xe', 'R2_xr', 'R3_nx', 'jump_host']'
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:01<00:00,  1.80s/it]
+==============================================================================+
| Genie Learn Summary for device R1_xe                                         |
+==============================================================================+
|  Connected to R1_xe                                                          |
|  -   Log: ops_after/connection_R1_xe.txt                                     |
|------------------------------------------------------------------------------|
|  Learnt feature 'routing'                                                    |
|  -  Ops structure:  ops_after/routing_iosxe_R1_xe_ops.txt                    |
|  -  Device Console: ops_after/routing_iosxe_R1_xe_console.txt                |
|==============================================================================|
(snip)

ログ比較チェック (genie diff)

genie diff で作業前と作業後のフォルダを指定するだけで比較できます。

(pyats)$ genie diff ops_before ops_after
1it [00:00, 117.44it/s]
+==============================================================================+
| Genie Diff Summary between directories ops_before/ and ops_after/            |
+==============================================================================+
|  File: routing_iosxe_R1_xe_ops.txt                                           |
|   - Identical                                                                |
|------------------------------------------------------------------------------|
|  File: routing_nxos_R3_nx_ops.txt                                            |
|   - Identical                                                                |
|------------------------------------------------------------------------------|
|  File: routing_iosxr_R2_xr_ops.txt                                           |
|   - Identical                                                                |
|------------------------------------------------------------------------------|

全3台とも “Identical” (同一) として作業前と作業後が同じ状況ということが確認できました。

実際には Diff ツールなどで確認している場合には当然差分が表示されるため、目視確認が必要ですが、genie diff では変動が期待される値についてはデフォルトで除外されるため、余計なノイズなく問題となる部分のみに注目して差分の確認が可能です。

デフォルトでのキー除外をやめたい場合は –no-default-exclusion オプションが使えます。下記が実行例です。

(pyats)$ genie diff ops_before ops_after --no-default-exclusion
1it [00:00, 108.82it/s]
+==============================================================================+
| Genie Diff Summary between directories ops_before/ and ops_after/            |
+==============================================================================+
|  File: routing_iosxe_R1_xe_ops.txt                                           |
|   - Diff can be found at ./diff_routing_iosxe_R1_xe_ops.txt                  |
|------------------------------------------------------------------------------|
|  File: routing_nxos_R3_nx_ops.txt                                            |
|   - Diff can be found at ./diff_routing_nxos_R3_nx_ops.txt                   |
|------------------------------------------------------------------------------|
|  File: routing_iosxr_R2_xr_ops.txt                                           |
|   - Diff can be found at ./diff_routing_iosxr_R2_xr_ops.txt                  |
|------------------------------------------------------------------------------|

–no-default-exclusion を指定した場合には差分が確認できるため ‘Identical’ と表示される代わりに diff_ ファイルが作成されいるのが分かります。ファイルの中身を見てみると、除外されていた ‘updated’ が差分として見えるようになったことが確認できます。

(pyats)$ cat ./diff_routing_iosxe_R1_xe_ops.txt
--- ops_before/routing_iosxe_R1_xe_ops.txt
+++ ops_after/routing_iosxe_R1_xe_ops.txt
info:
 vrf:
  default:
   address_family:
    ipv4:
     routes:
      10.2.2.2/32:
       next_hop:
        next_hop_list:
         1:
+          updated: 01:39:20
-          updated: 01:35:58
      10.3.3.3/32:
       next_hop:
(snip)

下記のように –exclude オプションを使うことで除外したいキーを増やすことができます。

(pyats)$ genie diff ops_before ops_after --exclude next_hop

–no-default-exclusion と –exclude を併用することでデフォルトの除外キーを無効にして自分好みの除外キーで差分を行うことも可能です。

(pyats)$ genie diff ops_before ops_after --no-default-exclusion --exclude next_hop

最後に R3_nx のループバックを shutdown し、R1_xe で差分が見えることを確認します。除外キーはデフォルトです。

(pyats)$ genie learn 'routing' --testbed-file tb.yaml --output ops_after_shut

続いて先ほどの ops_before と比較します。

(pyats)$ genie diff ops_before ops_after_shut
1it [00:00, 113.58it/s]
+==============================================================================+
| Genie Diff Summary between directories ops_before/ and ops_after_shut/       |
+==============================================================================+
|  File: routing_iosxe_R1_xe_ops.txt                                           |
|   - Diff can be found at ./diff_routing_iosxe_R1_xe_ops.txt                  |
|------------------------------------------------------------------------------|
|  File: routing_nxos_R3_nx_ops.txt                                            |
|   - Diff can be found at ./diff_routing_nxos_R3_nx_ops.txt                   |
|------------------------------------------------------------------------------|
|  File: routing_iosxr_R2_xr_ops.txt                                           |
|   - Diff can be found at ./diff_routing_iosxr_R2_xr_ops.txt                  |
|------------------------------------------------------------------------------|

3台ともに差分が出ているため、それぞれ開いて確認してみます。

(pyats)$ cat diff_routing_iosxe_R1_xe_ops.txt
--- ops_before/routing_iosxe_R1_xe_ops.txt
+++ ops_after_shut/routing_iosxe_R1_xe_ops.txt
info:
 vrf:
  default:
   address_family:
    ipv4:
     routes:
-      10.3.3.3/32:
-       active: True
-       metric: 3
-       next_hop:
-        next_hop_list:
-         1:
-          index: 1
-          next_hop: 172.16.12.2
-          outgoing_interface: GigabitEthernet2
-          updated: 01:14:09
-       route: 10.3.3.3/32
-       route_preference: 110
-       source_protocol: ospf
-       source_protocol_codes: O

(pyats)$ cat diff_routing_iosxr_R2_xr_ops.txt
--- ops_before/routing_iosxr_R2_xr_ops.txt
+++ ops_after_shut/routing_iosxr_R2_xr_ops.txt
info:
 vrf:
  default:
   address_family:
    ipv4:
     routes:
-      10.3.3.3/32:
-       active: True
-       metric: 2
-       next_hop:
-        next_hop_list:
-         1:
-          index: 1
-          next_hop: 172.16.23.3
-          outgoing_interface: GigabitEthernet0/0/0/1
-          updated: 01:14:09
-       route: 10.3.3.3/32
-       route_preference: 110
-       source_protocol: ospf
-       source_protocol_codes: O

(pyats)$ cat diff_routing_nxos_R3_nx_ops.txt
--- ops_before/routing_nxos_R3_nx_ops.txt
+++ ops_after_shut/routing_nxos_R3_nx_ops.txt
info:
 vrf:
  default:
   address_family:
    ipv4:
     routes:
-      10.3.3.3/32:
-       active: True
-       metric: 0
-       next_hop:
-        next_hop_list:
-         1:
-          index: 1
-          next_hop: 10.3.3.3
-          outgoing_interface: Loopback0
-          updated: 01:30:05
-         2:
-          index: 2
-          next_hop: 10.3.3.3
-          outgoing_interface: Loopback0
-          updated: 01:30:05
-       route: 10.3.3.3/32
-       route_preference: 0
-       source_protocol: direct

いずれも 10.3.3.3/32 が消失したことを示しており、source_protocol に着目すると R3_nx が ‘direct’ となっており、R3_nx のインタフェースがダウンしたのが原因だと特定することが可能です。

上記は genie learn での差分を取りましたが、genie diff は同様に genie parse のファイルに対しても同様の方法で比較が可能です。

また、Genie Model には記載されていないものになりますが、config を学習することができます。(しかしながら、これは抽象化されたものではないですが、比較はできます)

(pyats)$ genie diff config_before config_after
1it [00:00, 265.97it/s]
+==============================================================================+
| Genie Diff Summary between directories config_before/ and config_after/      |
+==============================================================================+
|  File: config_nxos_R3_nx_ops.txt                                             |
|   - Diff can be found at ./diff_config_nxos_R3_nx_ops.txt                    |
|------------------------------------------------------------------------------|

(pyats)$ cat ./diff_config_nxos_R3_nx_ops.txt
--- config_before/config_nxos_R3_nx_ops.txt
+++ config_after/config_nxos_R3_nx_ops.txt
interface loopback0:
- shutdown:

まとめ

  • プログラミング不要で作業ログ取得を効率化/自動化/高速化できるのが Genie CLI
  • genie parse は show コマンドのコンソール出力および構造化データを保存
  • genie learn は Genie Ops モデルを基にした show コマンドセットのコンソール出力及び抽象化された構造化データを保存
  • genie parser 呼び genie ops の両方でプリセットされる除外されるキー一覧(exclude)を持つ。genie diff のオプションで変更可能
  • genie diff はプリセット除外キーにより必要な差分だけを表示してくれるため、事前事後の比較が楽になる。

Genie CLI は現在の作業を効率化するために非常に有用な手段であり、自動化を行うまでの過渡期の手段としても使えるかと思いますので、ぜひネットワークの自動化を Genie CLI から初めてみてはどうでしょうか。

スポンサーリンク