pyATS/genieを触ってみよう

この記事は エーピーコミュニケーションズ [Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ap-com) の 12 日目の記事となります。

## 本記事のターゲット
この記事を順番に読んでいくとpyatsの環境がセットアップできるようになる。
genieでパースした内容を扱ってconfigの確認ができる

## あった方が良い知識
python 
YAML

## 実行環境
Mac book Air 10.15.1（19B88）
python 3.7.5

## インストール

基本は[公式ドキュメント](https://developer.cisco.com/docs/pyats/)を読み解いて進めていきます。

pyatsはpythonのライブラリです、そのため「pip」コマンドで簡単にインストールすることが可能です。

※サポートしているOSはMacとLinuxのみになります、windowsではインストール不可です(WSL上であれば可能)
※python3以上でサポートしているため、python2では利用ができません



```
#venvを作成
python -m venv pyATS 

#activate
source pyATS/bin/activate

#pipを最新のものに
pip install pip --upgrade 

#pyatsをinstall
pip install pyats
```

pyats.~~というライブラリが追加されていると思います、
pyatsのインストールはこれで一旦完了です。

早速どんなコマンドが使えるか、試してみたいと思いなす🍆

```
(pyATS) 11:39:39 Desktop $pyats --help
Usage:
  pyats <command> [options]

Commands:
    create              create scripts and libraries from template
    logs                command enabling log archive viewing in local browser
    run                 runs the provided script and output corresponding results.
    secret              utilities for working with secret strings.
    shell               enter Python shell and load a testbed file
    validate            utlities that helps to validate input files
    version             display currently installed pyATS version

General Options:
  -h, --help            Show help

Run 'pyats <command> --help' for more information on a command.
(pyATS) 11:40:04 Desktop $
```

少し前に書いた[記事](https://qiita.com/snamon/items/78eb3e314bf8e5787719)とここまではほぼ一緒ですねw
Unioconという接続用のライブラリもpip install pyatsで同時にインストールされています

さらに、pyatsの中にはgenieというパッケージがあります。
このパッケージはマルチベンダに対してコマンドをパースしてくれたり、抽象化されたコマンドで情報を取得してきたりするとてもイカしたパッケージです。

```
pip install genie
```

```
pip freeze

~snip

genie==19.11
genie.abstract==19.11
genie.conf==19.11
genie.harness==19.11
genie.libs.conf==19.11
genie.libs.filetransferutils==19.11
genie.libs.ops==19.11
genie.libs.parser==19.11
genie.libs.sdk==19.11
genie.libs.telemetry==19.11
genie.metaparser==19.11
genie.ops==19.11
genie.parsergen==19.11
genie.predcore==19.11
genie.telemetry==19.11
genie.trafficgen==19.11
genie.utils==19.11

snip~
```
バッチリゲットできました。
今回はこのgenieを利用して、機器からConfigの取得をさせていきたいと思います。
ちなみに、helpはこんな感じです。

```
(pyATS) 14:13:38 testbed $genie --help
Usage:
  genie <command> [options]

Commands:
    create              Create Testbed, parser, triggers, ...
    diff                Command to diff two snapshots saved to file or directory
    dnac                Command to learn DNAC features and save to file (Prototype)
    learn               Command to learn device features and save to file
    parse               Command to parse show commands
    run                 Run Genie triggers & verifications in pyATS runtime environment
    shell               enter Python shell and load a Genie testbed file and/or Pickled file

General Options:
  -h, --help            Show help

Run 'genie <command> --help' for more information on a command.
(pyATS) 14:13:44 testbed $
```

## 接続設定準備
pyats/genieでは接続対象の機器情報をYAML形式で記載しておく必要があります、これがtestbedファイルと呼ばるものです（Ansibleで例えるならinventoryファイルですね。

今回もCiscoDevnetのSandBoxで常に無料で使えるものをtestbedにしています。
コピペしていただいても利用可能かと思います。

```devnet_always.yml
---
testbed:
  name: SandBox

devices:
  sbx-n9kv-ao:
    alias: uut
    credentials:
      default:
        username: admin
        password: Admin_1234!
    connections:
      vty:
        protocol: ssh
        ip: sbx-nxos-mgmt.cisco.com
        port: 8181
    os: nxos
    type: nxos

  iosxr1:
    alias: rt
    credentials:
      default:
        username: admin
        password: C1sco12345
    connections:
      vty:
        protocol: ssh
        ip: sbx-iosxr-mgmt.cisco.com
        port: 8181
    os: iosxr
    type: iosxr

  csr1000v-1:
      alias: xe1
      credentials:
        default:
          username: developer
          password: C1sco12345
      connections:
        vty:
          protocol: ssh
          ip: ios-xe-mgmt-latest.cisco.com
          port: 8181
      os: iosxe
      type: iosxe

  csr1000v:
      alias: xe0
      credentials:
        default:
          username: developer
          password: C1sco12345
      connections:
        vty:
          protocol: ssh
          ip: ios-xe-mgmt.cisco.com
          port: 8181
      os: iosxe
      type: iosxe

```

少しだけ補足をします。

```補足.yml
testbed:
  #名前をつけているだけ。
  name: SandBox

#ここから接続先のDeveice情報
devices:
　#機器のホスト名と完全一致、ここが間違っていると接続後タイムアウトします。
  csr1000v:
      #デバイスを抽象化しています、このデバイスを選択するときはxe0と宣言してあげればOK
      alias: xe0
      #認証情報
      credentials:
        default:
          username: developer
          password: C1sco12345
      #接続方式がまとめられている
      connections:
        #SSHでの接続時に必要なポート情報などが載っている、via='vty'とするとここの情報で接続する
        vty:
          protocol: ssh
          ip: ios-xe-mgmt.cisco.com
          port: 8181
      #osのタイプを指定している、対応しているosは公式ドキュメントを参照
      os: iosxe
      type: iosxe
```

ここまで準備ができたら接続確認を実施してみましょう。

## genie shellコマンドで接続確認＆Parse＆Leanを試す
### 接続
それでは早速、接続していきましょう

```
(pyATS) 12:20:23 testbed $genie shell --testbed devnet_always.yml
Welcome to Genie Interactive Shell
==================================
Python 3.7.5 (default, Nov 27 2019, 18:39:20)
[Clang 11.0.0 (clang-1100.0.33.8)]

>>> from genie.testbed import load
>>> testbed = load('devnet_always.yml')
-------------------------------------------------------------------------------
>>>

```

genie shell --testbed [testbedファイル]コマンドで、testbedを読み込んだ状態で、shellが立ち上がります。

早速、機器に接続。

```
#まずDeviceを確認する。
>>> for i in testbed.devices:
...   print(i)
...
sbx-n9kv-ao
iosxr1
csr1000v-1
csr1000v
>>>

#iosxr1に接続
>>> testbed.devices['iosxr1'].connect(via='vty')
[2019-12-11 12:23:46,208] +++ iosxr1 logfile /tmp/iosxr1-cli-20191211T122346207.log +++
[2019-12-11 12:23:46,224] +++ Unicon plugin iosxr +++
Password:
[2019-12-11 12:23:49,600] +++ connection to spawn: ssh -l admin 64.103.37.3 -p 8181, id: 4567219984 +++
[2019-12-11 12:23:49,601] connection to iosxr1



RP/0/RP0/CPU0:iosxr1#
[2019-12-11 12:23:51,711] +++ initializing handle +++
[2019-12-11 12:23:51,713] +++ iosxr1: executing command 'terminal length 0' +++
terminal length 0
Wed Dec 11 04:54:19.980 UTC
RP/0/RP0/CPU0:iosxr1#
[2019-12-11 12:23:52,646] +++ iosxr1: executing command 'terminal width 0' +++
terminal width 0
Wed Dec 11 04:54:20.920 UTC
RP/0/RP0/CPU0:iosxr1#
[2019-12-11 12:23:53,464] +++ iosxr1: config +++
configure terminal
Wed Dec 11 04:54:21.732 UTC
RP/0/RP0/CPU0:iosxr1(config)#no logging console
RP/0/RP0/CPU0:iosxr1(config)#logging console disable
RP/0/RP0/CPU0:iosxr1(config)#line console
RP/0/RP0/CPU0:iosxr1(config-line)#exec-timeout 0 0
RP/0/RP0/CPU0:iosxr1(config-line)#absolute-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#session-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#line default
RP/0/RP0/CPU0:iosxr1(config-line)#exec-timeout 0 0
RP/0/RP0/CPU0:iosxr1(config-line)#absolute-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#session-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#commit
Wed Dec 11 04:54:31.024 UTC
RP/0/RP0/CPU0:iosxr1(config-line)#end
RP/0/RP0/CPU0:iosxr1#
'Password: \r\n\r\n\r\nRP/0/RP0/CPU0:iosxr1#'
>>>

#接続確認
>>> testbed.devices['iosxr1'].connected
True


#切断
>>> testbed.devices['iosxr1'].disconnect()
>>>

#もう一度確認
>>> testbed.devices['iosxr1'].connected
False
```

接続ができました、よく見るとセットアップとして、設定変更をしているようです。
環境によってはconfigure teminalに入った時に監視で検知されるような環境もあるでしょうし、若干注意が必要ですね。

```
RP/0/RP0/CPU0:iosxr1(config)#no logging console
RP/0/RP0/CPU0:iosxr1(config)#logging console disable
RP/0/RP0/CPU0:iosxr1(config)#line console
RP/0/RP0/CPU0:iosxr1(config-line)#exec-timeout 0 0
RP/0/RP0/CPU0:iosxr1(config-line)#absolute-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#session-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#line default
RP/0/RP0/CPU0:iosxr1(config-line)#exec-timeout 0 0
RP/0/RP0/CPU0:iosxr1(config-line)#absolute-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#session-timeout 0
RP/0/RP0/CPU0:iosxr1(config-line)#commit
```

commitまでしているので、前回commitし忘れていた！なんてのがあるとこのタイミングで変更になってしまいますね。（まぁないかな）


ちなみに、ここでtestbedに定義しているaliasでも接続することが可能です。

```抜粋.yml
  iosxr1:
    alias: rt
```

aliasをrtとしているのでdevices['rt']と指定します

```
>>> testbed.devices['rt'].connect(via='vty')
Password:
[2019-12-11 12:31:29,856] +++ connection to spawn: ssh -l admin 64.103.37.3 -p 8181, id: 4566231184 +++
[2019-12-11 12:31:29,857] connection to iosxr1

```

### Parse
続いてParseです、例えば「show ip route」と叩くとその結果が辞書になって帰ってきてくれます。
対応しているコマンドはgenieの[公式ドキュメント](https://developer.cisco.com/docs/genie-docs/)を参照しましょう。

今回は以下のコマンドをParseしたいと思います。
show route ipv4

早速実行

```
>>> testbed.devices['rt'].parse('show route ipv4')
[2019-12-11 12:37:27,360] +++ iosxr1: executing command 'show route ipv4' +++
show route ipv4
Wed Dec 11 05:07:55.668 UTC

Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path
       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, E - EGP
       i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2
       ia - IS-IS inter area, su - IS-IS summary null, * - candidate default
       U - per-user static route, o - ODR, L - local, G  - DAGR, l - LISP
       A - access/subscriber, a - Application route
       M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path

Gateway of last resort is 10.10.20.254 to network 0.0.0.0

S*   0.0.0.0/0 [1/0] via 10.10.20.254, 1w1d
L    1.1.1.100/32 is directly connected, 1w1d, Loopback100
L    1.1.1.200/32 is directly connected, 1w1d, Loopback200
C    10.10.20.0/24 is directly connected, 1w1d, MgmtEth0/RP0/CPU0/0
L    10.10.20.175/32 is directly connected, 1w1d, MgmtEth0/RP0/CPU0/0
RP/0/RP0/CPU0:iosxr1#
{'vrf': {'default': {'address_family': {'ipv4': {'routes': {'0.0.0.0/0': {'route': '0.0.0.0/0', 'active': True, 'metric': 0, 'route_preference': 1, 'source_protocol_codes': 'S*', 'source_protocol': 'static', 'next_hop': {'next_hop_list': {1: {'index': 1, 'next_hop': '10.10.20.254', 'updated': '1w1d'}}}}, '1.1.1.100/32': {'route': '1.1.1.100/32', 'active': True, 'source_protocol_codes': 'L', 'source_protocol': 'local', 'next_hop': {'outgoing_interface': {'Loopback100': {'outgoing_interface': 'Loopback100', 'updated': '1w1d'}}}}, '1.1.1.200/32': {'route': '1.1.1.200/32', 'active': True, 'source_protocol_codes': 'L', 'source_protocol': 'local', 'next_hop': {'outgoing_interface': {'Loopback200': {'outgoing_interface': 'Loopback200', 'updated': '1w1d'}}}}, '10.10.20.0/24': {'route': '10.10.20.0/24', 'active': True, 'source_protocol_codes': 'C', 'source_protocol': 'connected', 'next_hop': {'outgoing_interface': {'MgmtEth0/RP0/CPU0/0': {'outgoing_interface': 'MgmtEth0/RP0/CPU0/0', 'updated': '1w1d'}}}}, '10.10.20.175/32': {'route': '10.10.20.175/32', 'active': True, 'source_protocol_codes': 'L', 'source_protocol': 'local', 'next_hop': {'outgoing_interface': {'MgmtEth0/RP0/CPU0/0': {'outgoing_interface': 'MgmtEth0/RP0/CPU0/0', 'updated': '1w1d'}}}}}}}}}}
>>>

```

簡単に取得することができました、CLIでの実行結果＋辞書で値が戻ってきます。

```
#変数の格納して
ipv4Route = testbed.devices['rt'].parse('show route ipv4')


#ルーティングテーブルに載ってるルートのみ取り出す
>>> for j in ipv4Route['vrf']['default']['address_family']['ipv4']['routes']:
...   print(j)
...
0.0.0.0/0
1.1.1.100/32
1.1.1.200/32
10.10.20.0/24
10.10.20.175/32
>>>

#ごちゃついているけど、整形して必要な情報のみ抜き出すこともわりと簡単
>>> for j in ipv4Route['vrf']['default']['address_family']['ipv4']['routes']:
...   print("Route:{}  Protocol:{}".format(j,ipv4Route['vrf']['default']['address_family']['ipv4']['routes'][j]['source_protocol']))
...
Route:0.0.0.0/0  Protocol:static
Route:1.1.1.100/32  Protocol:local
Route:1.1.1.200/32  Protocol:local
Route:10.10.20.0/24  Protocol:connected
Route:10.10.20.175/32  Protocol:local
>>>
```

### Learn
続いてLearnというのもを実行してみましょう、これがまさに機器によらず抽象的なコマンド情報取得ができる物になります。

[公式ドキュメント](https://developer.cisco.com/docs/genie-docs/)のOps/Confを見てみます。

簡単ですが主要で使いそうなものまとめてみました（個人の見解です）

|コマンド|
|---|
| acl |
| arp |
| bgp |
| dot1x |
| hsrp |
| interface |
| lag |
| lldp |
| ntp |
| ospf |
| platform |
| prefix_list |
| rip |
| route_policy |
| routing |
| static_routing |
| stp |
| vlan |


それでは早速、routingを試してみましょう
※公式ドキュメントからは発見できなかったんですが、configと指定するとrunningconfig取ってきてくれます

```
>>> testbed.devices['iosxr1'].learn('routing')
[2019-12-11 13:05:16,769] +++ iosxr1: executing command 'show route ipv4' +++
show route ipv4
Wed Dec 11 05:35:45.091 UTC

Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path
       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, E - EGP
       i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2
       ia - IS-IS inter area, su - IS-IS summary null, * - candidate default
       U - per-user static route, o - ODR, L - local, G  - DAGR, l - LISP
       A - access/subscriber, a - Application route
       M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path

Gateway of last resort is 10.10.20.254 to network 0.0.0.0

S*   0.0.0.0/0 [1/0] via 10.10.20.254, 1w1d
L    1.1.1.100/32 is directly connected, 1w1d, Loopback100
L    1.1.1.200/32 is directly connected, 1w1d, Loopback200
C    10.10.20.0/24 is directly connected, 1w1d, MgmtEth0/RP0/CPU0/0
L    10.10.20.175/32 is directly connected, 1w1d, MgmtEth0/RP0/CPU0/0
RP/0/RP0/CPU0:iosxr1#
[2019-12-11 13:05:17,984] +++ iosxr1: executing command 'show route ipv6' +++
show route ipv6
Wed Dec 11 05:35:46.208 UTC

% No matching routes found

RP/0/RP0/CPU0:iosxr1#
Could not learn <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'>
Parser Output is empty
+====================================================================================================================================================+
| Commands for learning feature 'Routing'                                                                                                            |
+====================================================================================================================================================+
| - Parsed commands                                                                                                                                  |
|----------------------------------------------------------------------------------------------------------------------------------------------------|
|   cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpDistributor'>                                                                       |
|====================================================================================================================================================|
| - Commands with empty output                                                                                                                       |
|----------------------------------------------------------------------------------------------------------------------------------------------------|
|   cmd: <class 'genie.libs.parser.iosxr.show_routing.ShowRouteIpv6Distributor'>                                                                     |
|====================================================================================================================================================|
<Routing object at 0x110e7d090>
>>>
```

learn('routing')を実行すると、下記コマンド実行してParseまでしてくれています。
「show route ipv4」
「show route ipv6」


なのでまた同じ内容を出力してみましょう。

```
>>> for j in routing.info['vrf']['default']['address_family']['ipv4']['routes']:
...   print(j)
...
10.10.20.175/32
10.10.20.0/24
1.1.1.200/32
1.1.1.100/32
0.0.0.0/0
>>>
```

前回とは若干構造が異なっています、下記を参考に欲しい情報のところまで潜ります。（公式ドキュメントからリンクがあり辿り着けると思います）
https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/_models/routing.pdf

※このドキュメントに今回のOpsの対応機器情報がありました、[NXOS,IOSXR,IOSXE]のみ対応のようです。

それでは別の機種に対しても同様のコマンド(routing)で情報を取得してみましょう。

```
# NXOSに接続
>>> testbed.devices['uut'].connect()

Welcome to the DevNet Always On Sandbox for Open NX-OS

This is a shared sandbox available for anyone to use to
test APIs, explore features, and test scripts.  Please
keep this in mind as you use it, and respect others use.

The following programmability features are already enabled:
  - NX-API
  - NETCONF, RESTCONF, gRPC
  - Native NX-OS and OpenConfig YANG Models

Thanks for stopping by.

[2019-12-11 13:16:10,322] +++ connection to spawn: ssh -l admin 64.103.37.14 -p 8181, id: 4581872976 +++
[2019-12-11 13:16:10,324] connection to sbx-n9kv-ao
Password:

Cisco NX-OS Software
Copyright (c) 2002-2018, Cisco Systems, Inc. All rights reserved.
Nexus 9000v software ("Nexus 9000v Software") and related documentation,
files or other reference materials ("Documentation") are
the proprietary property and confidential information of Cisco
Systems, Inc. ("Cisco") and are protected, without limitation,
pursuant to United States and International copyright and trademark
laws in the applicable jurisdiction which provide civil and criminal
penalties for copying or distribution without Cisco's authorization.

Any use or disclosure, in whole or in part, of the Nexus 9000v Software
or Documentation to any third party for any purposes is expressly
prohibited except as otherwise authorized by Cisco in writing.
The copyrights to certain works contained herein are owned by other
third parties and are used and distributed under license. Some parts
of this software may be covered under the GNU Public License or the
GNU Lesser General Public License. A copy of each such license is
available at
http://www.gnu.org/licenses/gpl.html and
http://www.gnu.org/licenses/lgpl.html
***************************************************************************
*  Nexus 9000v is strictly limited to use for evaluation, demonstration   *
*  and NX-OS education. Any use or disclosure, in whole or in part of     *
*  the Nexus 9000v Software or Documentation to any third party for any   *
*  purposes is expressly prohibited except as otherwise authorized by     *
*  Cisco in writing.                                                      *
***************************************************************************
sbx-n9kv-ao#
[2019-12-11 13:16:12,786] +++ initializing handle +++
[2019-12-11 13:16:12,788] +++ sbx-n9kv-ao: executing command 'term length 0' +++
term length 0
sbx-n9kv-ao#
[2019-12-11 13:16:13,591] +++ sbx-n9kv-ao: executing command 'term width 511' +++
term width 511
sbx-n9kv-ao#
[2019-12-11 13:16:15,258] +++ sbx-n9kv-ao: executing command 'terminal session-timeout 0' +++
terminal session-timeout 0
sbx-n9kv-ao#
[2019-12-11 13:16:15,619] +++ sbx-n9kv-ao: config +++
config term
Enter configuration commands, one per line. End with CNTL/Z.
sbx-n9kv-ao(config)# no logging console
sbx-n9kv-ao(config)# line console
sbx-n9kv-ao(config-console)# exec-timeout 0
sbx-n9kv-ao(config-console)# terminal width 511
sbx-n9kv-ao(config-console)# end
sbx-n9kv-ao#
'\r\nWelcome to the DevNet Always On Sandbox for Open NX-OS\r\n\r\nThis is a shared sandbox available for anyone to use to\r\ntest APIs, explore features, and test scripts.  Please\r\nkeep this in mind as you use it, and respect others use.\r\n\r\nThe following programmability features are already enabled:\r\n  - NX-API\r\n  - NETCONF, RESTCONF, gRPC\r\n  - Native NX-OS and OpenConfig YANG Models\r\n\r\nThanks for stopping by.\r\nPassword: \r\n\r\nCisco NX-OS Software\r\nCopyright (c) 2002-2018, Cisco Systems, Inc. All rights reserved.\r\nNexus 9000v software ("Nexus 9000v Software") and related documentation,\r\nfiles or other reference materials ("Documentation") are\r\nthe proprietary property and confidential information of Cisco\r\nSystems, Inc. ("Cisco") and are protected, without limitation,\r\npursuant to United States and International copyright and trademark\r\nlaws in the applicable jurisdiction which provide civil and criminal\r\npenalties for copying or distribution without Cisco\'s authorization.\r\n\r\nAny use or disclosure, in whole or in part, of the Nexus 9000v Software\r\nor Documentation to any third party for any purposes is expressly\r\nprohibited except as otherwise authorized by Cisco in writing.\r\nThe copyrights to certain works contained herein are owned by other\r\nthird parties and are used and distributed under license. Some parts\r\nof this software may be covered under the GNU Public License or the\r\nGNU Lesser General Public License. A copy of each such license is\r\navailable at\r\nhttp://www.gnu.org/licenses/gpl.html and\r\nhttp://www.gnu.org/licenses/lgpl.html\r\n***************************************************************************\r\n*  Nexus 9000v is strictly limited to use for evaluation, demonstration   *\r\n*  and NX-OS education. Any use or disclosure, in whole or in part of     *\r\n*  the Nexus 9000v Software or Documentation to any third party for any   *\r\n*  purposes is expressly prohibited except as otherwise authorized by     *\r\n*  Cisco in writing.                                                      *\r\n***************************************************************************\r\n\rsbx-n9kv-ao# '
>>>

# すかさず、Ops
>>> routing_nxos = testbed.devices['uut'].learn('routing')
[2019-12-11 13:18:01,705] +++ sbx-n9kv-ao: executing command 'show ip route vrf all' +++
show ip route vrf all
IP Route Table for VRF "default"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]
'%<string>' in via output denotes VRF <string>

172.16.0.1/32, ubest/mbest: 2/0, attached
    *via 172.16.0.1, Lo1, [0/0], 14:07:42, local
    *via 172.16.0.1, Lo1, [0/0], 14:07:42, direct
172.16.1.0/30, ubest/mbest: 1/0, attached
    *via 172.16.1.1, Eth1/5, [0/0], 14:07:04, direct
172.16.1.1/32, ubest/mbest: 1/0, attached
    *via 172.16.1.1, Eth1/5, [0/0], 14:07:04, local
172.16.100.0/24, ubest/mbest: 1/0, attached
    *via 172.16.100.1, Vlan100, [0/0], 14:06:34, direct
172.16.100.1/32, ubest/mbest: 1/0, attached
    *via 172.16.100.1, Vlan100, [0/0], 14:06:34, local
172.16.101.0/24, ubest/mbest: 1/0, attached
    *via 172.16.101.1, Vlan101, [0/0], 14:06:34, direct
172.16.101.1/32, ubest/mbest: 1/0, attached
    *via 172.16.101.1, Vlan101, [0/0], 14:06:34, local
172.16.102.0/24, ubest/mbest: 1/0, attached
    *via 172.16.102.1, Vlan102, [0/0], 14:06:34, direct
172.16.102.1/32, ubest/mbest: 1/0, attached
    *via 172.16.102.1, Vlan102, [0/0], 14:06:34, local
172.16.103.0/24, ubest/mbest: 1/0, attached
    *via 172.16.103.1, Vlan103, [0/0], 14:06:34, direct
172.16.103.1/32, ubest/mbest: 1/0, attached
    *via 172.16.103.1, Vlan103, [0/0], 14:06:34, local
172.16.104.0/24, ubest/mbest: 1/0, attached
    *via 172.16.104.1, Vlan104, [0/0], 14:06:34, direct
172.16.104.1/32, ubest/mbest: 1/0, attached
    *via 172.16.104.1, Vlan104, [0/0], 14:06:34, local
172.16.105.0/24, ubest/mbest: 1/0, attached
    *via 172.16.105.1, Vlan105, [0/0], 14:06:34, direct
172.16.105.1/32, ubest/mbest: 1/0, attached
    *via 172.16.105.1, Vlan105, [0/0], 14:06:34, local

IP Route Table for VRF "management"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]
'%<string>' in via output denotes VRF <string>

0.0.0.0/0, ubest/mbest: 1/0
    *via 10.10.20.254, [1/0], 14:07:36, static
10.10.20.0/24, ubest/mbest: 1/0, attached
    *via 10.10.20.95, mgmt0, [0/0], 14:07:37, direct
10.10.20.95/32, ubest/mbest: 1/0, attached
    *via 10.10.20.95, mgmt0, [0/0], 14:07:37, local

sbx-n9kv-ao#
[2019-12-11 13:18:02,240] +++ sbx-n9kv-ao: executing command 'show ipv6 route vrf all' +++
show ipv6 route vrf all
IPv6 Routing Table for VRF "default"
'*' denotes best ucast next-hop
'**' denotes best mcast next-hop
'[x/y]' denotes [preference/metric]


sbx-n9kv-ao#
+====================================================================================================================================================+
| Commands for learning feature 'Routing'                                                                                                            |
+====================================================================================================================================================+
| - Parsed commands                                                                                                                                  |
|----------------------------------------------------------------------------------------------------------------------------------------------------|
|   cmd: <class 'genie.libs.parser.nxos.show_routing.ShowIpRoute'>, arguments: {'vrf':'all'}                                                         |
|   cmd: <class 'genie.libs.parser.nxos.show_routing.ShowIpv6Route'>, arguments: {'vrf':'all'}                                                       |
|====================================================================================================================================================|
>>>

# またすかさず、ルート情報取得
>>> for j in routing_nxos.info['vrf']['default']['address_family']['ipv4']['routes']:
...   print(j)
...
172.16.105.1/32
172.16.105.0/24
172.16.104.1/32
172.16.104.0/24
172.16.103.1/32
172.16.103.0/24
172.16.102.1/32
172.16.102.0/24
172.16.101.1/32
172.16.101.0/24
172.16.100.1/32
172.16.100.0/24
172.16.1.1/32
172.16.1.0/30
172.16.0.1/32
>>>

```

ログの通り、同じ辞書の形式になったことがお分かり頂けたかと思います。
うーん、これは便利。

# まとめ
前回、備忘録的にまとめてものをもう少し細かく＆Genieについて触れてみました。
genie shellで完結させましたが、もう少し複雑なことしたい！って思ったらPythonをガシガシ書いていくけば利用範囲はかなり広がると思います。

Python？やだよそんなもん。って方でも使えるような仕組みもあるのでぜひ調べてみてください。

コードが全然書けないので私も四苦八苦しています、一緒に勉強してくれる方も募集中です
Twitter:https://twitter.com/usagi_automate