pyATS/Genie : YAML でネットワーク構成を書いて、ネットワーク機器へ接続/設定を行う

今回は pyATS / Genie を使うにあたって、避けては通れないネットワーク構成を記載する YAML ファイルについてと、簡単に python でネットワーク機器へ接続して show コマンドを実行したり設定したりする方法を紹介したいと思います。

pyATS / Genie をまだインストールしていない方は下記記事を参考にまずはインストールしてくださいね。

今回使用するネットワーク構成

pyATS & Genie のドキュメントページで提供されている VIRL ファイルのトポロジーを使いたいと思います。VIRL はシスコが提供している仮想ルータを使って仮想ネットワークを構築できるツールです。CCNA/CCNP/CCIE の勉強のみならず、実機器を使わずネットワークの挙動を把握するのにも便利なツールです。(ただし、無料ではなく年間 200USD くらいかかります。)

と少し話がズレましたが、Genie がサンプル例用に提供している VIRL ファイルをこちらからゲットできます。example_testbed.virl というファイルをダウンロードし、VIRL で起動してください。

構成としては下記のようなルータ2台構成(IOS-XE と NX-OS)になっており、各リンクで OSPF Neighbor が設定され、ルータのループバックアドレスで iBGP ネイバーが設定されています。

左側の csr1000v-1 にログインして手動でログを取得した情報。ネットワークエンジニアの方なら、何となく構成が分かるかと思います。設定については上の virl ファイルをテキストエディタで開くと確認できます。

csr1000v-1#sh ip int brief
Interface              IP-Address      OK? Method Status                Protocol
GigabitEthernet1       172.16.1.84     YES TFTP   up                    up      
GigabitEthernet2       10.0.1.1        YES TFTP   up                    up      
GigabitEthernet3       10.0.2.1        YES TFTP   up                    up      
GigabitEthernet4       unassigned      YES unset  administratively down down    
Loopback0              10.1.1.1        YES TFTP   up                    up      
Loopback1              10.11.11.11     YES TFTP   up                    up      
csr1000v-1#sh ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.2.2.2          1   FULL/DR         00:00:35    10.0.1.2        GigabitEthernet2
10.2.2.2          1   FULL/DR         00:00:38    10.0.2.2        GigabitEthernet3
csr1000v-1#sh ip bgp sum
BGP router identifier 10.1.1.1, local AS number 65000
BGP table version is 3, main routing table version 3
2 network entries using 496 bytes of memory
2 path entries using 272 bytes of memory
2/2 BGP path/bestpath attribute entries using 560 bytes of memory
0 BGP route-map cache entries using 0 bytes of memory
0 BGP filter-list cache entries using 0 bytes of memory
BGP using 1328 total bytes of memory
BGP activity 3/1 prefixes, 3/1 paths, scan interval 60 secs

Neighbor        V           AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.2.2.2        4        65000       7       7        3    0    0 00:02:49        1

ネットワーク構成を記述する testbed.yaml

ネットワークの自動化を行うにあたり、ネットワークの構成を把握し、それを testbed.yaml として作成する必要があります。tb.yaml とか topology.yaml とかファイル名は何でもいいんですが、testbed.yaml としておきます。

上の Genie のドキュメントで提供されている example_testbed.virl を使う場合、この virl ファイルをものに作成された testbed.yaml も提供されています。下記のように仮想環境のディレクトリ($VIRTUAL_ENV)へ移動し、wget などでファイルをゲットしてエディタで必要な箇所を編集しましょう。

(genie)$ cd $VIRTUAL_ENV
(genie)$ wget https://pubhub.devnetcloud.com/media/pyats-packages/docs/_downloads/testbed.yaml
(genie)$ vi testbed.yaml

testbed.yaml の中身はこんな感じ。ハイライトしている箇所は適宜環境に合わせて変更する必要がある部分になります。VIRL では各ルータ毎に TCP ポート 170XX といった形でコンソールアクセス用のポートがランダムに割り当てられるため、環境にあったものに変更してください。実機器でコンソールではなく通常の Telnet でポートがデフォルトであれば、port: 23 と書いてもいいですし、その行を削除しても構いません。

testbed:
    name: 'virl'

devices:
    nx-osv-1:
        type: "NX-OSv 9000"
        os: "nxos"
        alias: uut
        tacacs:
            login_prompt: 'login:'
            password_prompt: 'Password:'
            username: admin
        passwords:
            tacacs: admin
            enable: admin
            line: admin
        connections:
            defaults:
                class: 'unicon.Unicon'
            a:
                protocol: telnet
                ip: 172.16.1.1
                port: 17040
        custom:
            abstraction:
                order: [os]
    csr1000v-1:
        type: asr1k
        os: "iosxe"
        alias: helper
        tacacs:
            login_prompt: 'login:'
            password_prompt: 'Password:'
            username: cisco
        passwords:
            tacacs: cisco
            enable: cisco
            line: cisco
        connections:
            defaults:
                class: 'unicon.Unicon'
            a:
                protocol: telnet
                ip: 172.16.1.1
                port: 17038
        custom:
            abstraction:
                order: [os]

各項目について詳細の説明は省きますが、YAML での記述という点と、ネットワークエンジニアの方であれば、実機器を代わりに使う場合でも、上を参考にして書くことができるのではないかと思います。

重要な点としては、デバイス名と os になります。デバイス名(Line 5, 27) はデバイスのホスト名と一致している必要があります。また、os にはデバイスの os (iosxe, iosxr, nxos 等)を指定します。os は Genie のライブラリ内で os 毎に処理を振り分けるのに使われます。

ちなみに Line 18-19、24-26、40-41、46-48 はデフォルト扱いとなり、最新のバージョンでは書く必要はなくなりました。なので、シンプルにすると下記のような感じになります。

testbed:
    name: 'virl'

devices:
    nx-osv-1:
        type: "NX-OSv 9000"
        os: "nxos"
        alias: uut
        tacacs:
            login_prompt: 'login:'
            password_prompt: 'Password:'
            username: admin
        passwords:
            tacacs: admin
            enable: admin
            line: admin
        connections:
            a:
                protocol: telnet
                ip: 172.16.1.1
                port: 17040
    csr1000v-1:
        type: asr1k
        os: "iosxe"
        alias: helper
        tacacs:
            login_prompt: 'login:'
            password_prompt: 'Password:'
            username: cisco
        passwords:
            tacacs: cisco
            enable: cisco
            line: cisco
        connections:
            a:
                protocol: telnet
                ip: 172.16.1.1
                port: 17038

少しスッキリしましたね。実機器ではコンソールもあるし、マネージメントとして telnet/ssh もあると思います。その場合は下記のように connections セクションに追加するだけです。

(snip)
        connections:
            console:
                protocol: telnet
                ip: 172.16.1.1
                port: 17040
            telnet:
                protocol: telnet
                ip: 192.168.1.1
            ssh:
                protocol: ssh
                ip: 192.168.1.1
(snip)

ここまでが testbed.yaml の簡単な説明でした。では python を使ってデバイスにアクセスしてみます。

Genie/Unicon を使ってデバイスへアクセスする

Unicon とは pyATS / Genie がデフォルトで使っている機器へのコネクションライブラリです。

ここからは上で作成した testbed.yaml を使って簡単な python コードで機器へ接続、そしてちょっとした操作を行ってみたいと思います。

python を知らない?きっと大丈夫です。ここでは難しいことはしないのと、できる限り説明を書きます。

それでは python の仮想環境にいる状態で python コマンドを打ちます。するとpython のインタープリターに入り、ここで簡単な python コードを投入して実行することができます。

(genie)$ python
Python 3.6.5 (default, Apr  5 2018, 11:31:35)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

それではデバイス ‘csr1000v-1’ へ接続してみます。1行目ではライブラリの読み込み、2行目で作成した testbed.yaml を読み込み、変数 testbed へテストベッドオブジェクトを格納しています。3行目ではそのテストベッドオブジェクトから特定の機器 ‘csr1000v-1’ を指定して変数 device へデバイスオブジェクトを格納し、4行目でデバイスで接続します。オブジェクトが何やらとか少し、とっつきにくいかもしれませんが、慣れるとコピペでできてしまうレベルですよね。

>>> from genie.conf import Genie
>>> testbed = Genie.init('testbed.yaml')
>>> device = testbed.devices['csr1000v-1']
>>> device.connect()

device.connect() で接続した場合の出力は下記のようになります。機器へ接続した場合にはデフォルトで show version でバージョン情報の取得、自動化に必要となる terminal lengh 0 等が自動で投入されます。※ connect() にオプションを渡すことで自動で投入される設定やコマンドを無効にしたり、変更することが可能です。

>>> device.connect()
[2019-02-09 09:46:50,397] +++ csr1000v-1 logfile /tmp/csr1000v-1-cli-20190209T094650396.log +++
[2019-02-09 09:46:50,397] +++ Unicon plugin iosxe +++
[2019-02-09 09:46:50,400] +++ connection to spawn: telnet 172.16.1.1 17038, id: 4435595728 +++
[2019-02-09 09:46:50,401] connection to csr1000v-1
[2019-02-09 09:46:50,404] telnet 172.16.1.1 17038
Trying 172.16.1.1...
Connected to 172.16.1.1.
Escape character is '^]'.

csr1000v-1>
csr1000v-1>
csr1000v-1>
[2019-02-09 09:46:52,681] +++ initializing handle +++
enable
Password:
csr1000v-1#
[2019-02-09 09:46:53,197] +++ csr1000v-1: executing command 'term length 0' +++
term length 0
csr1000v-1#
[2019-02-09 09:46:53,458] +++ csr1000v-1: executing command 'term width 0' +++
term width 0
csr1000v-1#
[2019-02-09 09:46:53,734] +++ csr1000v-1: executing command 'show version' +++
show version
Cisco IOS XE Software, Version 16.09.01
Cisco IOS Software [Fuji], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 16.9.1, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2018 by Cisco Systems, Inc.
Compiled Tue 17-Jul-18 16:57 by mcpre


Cisco IOS-XE software, Copyright (c) 2005-2018 by cisco Systems, Inc.
All rights reserved.  Certain components of Cisco IOS-XE software are
licensed under the GNU General Public License ("GPL") Version 2.0.  The
software code licensed under GPL Version 2.0 is free software that comes
with ABSOLUTELY NO WARRANTY.  You can redistribute and/or modify such
GPL code under the terms of GPL Version 2.0.  For more details, see the
documentation or "License Notice" file accompanying the IOS-XE software,
or the applicable URL provided on the flyer accompanying the IOS-XE
software.


ROM: IOS-XE ROMMON

csr1000v-1 uptime is 3 hours, 20 minutes
Uptime for this control processor is 3 hours, 22 minutes
System returned to ROM by reload
System image file is "bootflash:packages.conf"
Last reload reason: Reload Command



This product contains cryptographic features and is subject to United
States and local country laws governing import, export, transfer and
use. Delivery of Cisco cryptographic products does not imply
third-party authority to import, export, distribute or use encryption.
Importers, exporters, distributors and users are responsible for
compliance with U.S. and local country laws. By using this product you
agree to comply with applicable laws and regulations. If you are unable
to comply with U.S. and local laws, return this product immediately.

A summary of U.S. laws governing Cisco cryptographic products may be found at:


If you require further assistance please contact us by sending email to
export@cisco.com.

License Level: ax
License Type: Default. No valid license found.
Next reload license Level: ax

cisco CSR1000V (VXE) processor (revision VXE) with 1217428K/3075K bytes of memory.
Processor board ID 9E5NGFET7W6
4 Gigabit Ethernet interfaces
32768K bytes of non-volatile configuration memory.
3018864K bytes of physical memory.
7774207K bytes of virtual hard disk at bootflash:.
0K bytes of WebUI ODM Files at webui:.

Configuration register is 0x2102

csr1000v-1#
[2019-02-09 09:46:54,110] +++ csr1000v-1: config +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
csr1000v-1(config)#no logging console
csr1000v-1(config)#line console 0
csr1000v-1(config-line)#exec-timeout 0
csr1000v-1(config-line)#end
csr1000v-1#
"Escape character is '^]'.\r\n\r\ncsr1000v-1>\r\ncsr1000v-1>\r\ncsr1000v-1>"
>>>

testbed.yaml があればたったの 4行 で機器に接続できます。しかも testbed.yaml に記載したパスワードなどの投入などは自動で行われます。また os が違ってもそれは同様です。同じことを nx-osv-1 に対しても行ってみましょう。

>>> device2 = testbed.devices['nx-osv-1']
>>> device2.connect()
[2019-02-09 09:54:47,445] +++ nx-osv-1 logfile /tmp/nx-osv-1-cli-20190209T095447444.log +++
[2019-02-09 09:54:47,445] +++ Unicon plugin nxos +++
[2019-02-09 09:54:47,449] +++ connection to spawn: telnet 172.25.192.134 17040, id: 4441247304 +++
[2019-02-09 09:54:47,450] connection to nx-osv-1
[2019-02-09 09:54:47,453] telnet 172.16.1.1 17040
Trying 172.16.1.1...
Connected to 172.16.1.1.
Escape character is '^]'.

User Access Verification
nx-osv-1 login: admin
Password:

Cisco NX-OS Software
Copyright (c) 2002-2016, Cisco Systems, Inc. All rights reserved.
NX-OSv software ("NX-OSv 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 NX-OSv 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
 and

***************************************************************************
*  NX-OSv is strictly limited to use for evaluation, demonstration and    *
*  NX-OS education. NX-OSv is provided as-is and is not supported by      *
*  Cisco's Technical Advisory Center. Any use or disclosure, in whole or  *
*  in part of the NX-OSv Software or Documentation to any third party for *
*  any purposes is expressly prohibited except as otherwise authorized by *
*  Cisco in writing.                                                      *
***************************************************************************
nx-osv-1#
[2019-02-09 09:54:49,022] +++ initializing handle +++
[2019-02-09 09:54:49,023] +++ nx-osv-1: executing command 'term length 0' +++
term length 0
nx-osv-1#
[2019-02-09 09:54:49,279] +++ nx-osv-1: executing command 'term width 511' +++
term width 511
nx-osv-1#
[2019-02-09 09:54:49,546] +++ nx-osv-1: executing command 'terminal session-timeout 0' +++
terminal session-timeout 0
nx-osv-1#
[2019-02-09 09:54:49,821] +++ nx-osv-1: config +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
nx-osv-1(config)# no logging console
nx-osv-1(config)# line console
nx-osv-1(config-console)# exec-timeout 0
nx-osv-1(config-console)# terminal width 511
nx-osv-1(config-console)# end
nx-osv-1#
'Escape character is \'^]\'.\r\n\r\nUser Access 
(snip)
>>>

同じですよね?当然 os が異なるので、適切な設定やコマンドが投入されますが、コードの観点では全く同じとなります。

では show コマンドを device ‘csr1000v-1’ へ実行してみましょう。show コマンドやコマンドを送信するには execute() を使います。() の中に show コマンドを記載するだけです。

>>> device.execute('show ip ospf neighbor')
[2019-02-09 09:59:00,546] +++ csr1000v-1: executing command 'show ip ospf neighbor' +++
show ip ospf neighbor

Neighbor ID     Pri   State           Dead Time   Address         Interface
10.2.2.2          1   FULL/DR         00:00:35    10.0.1.2        GigabitEthernet2
10.2.2.2          1   FULL/DR         00:00:31    10.0.2.2        GigabitEthernet3
csr1000v-1#
(snip)
>>>

では設定は?というと、configure() を使います。() の中に設定したい内容を入れて実行すると、自動的に conf t をしてコンフィグモードに入り、また設定投入後は end で設定モードを抜けてくれます。nxos や iosxr でも同じです。(iosxr では ちゃんとconfigure/commit などをしてくれます)

>>> device.configure('no ip domain lookup')
[2019-02-09 10:02:58,246] +++ csr1000v-1: config +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
csr1000v-1(config)#no ip domain lookup
csr1000v-1(config)#end
csr1000v-1#
'no ip domain lookup\r\n'
>>>

ここまでで、すでにお気づきかもしれませんが、connect() をすると機器へのセッションを維持した状態となっていますので、必要なくなれば disconnect() を行います。デバイスへのセッションが存在するかは is_connect() で確認が可能です。

>>> device.is_connected()
True
>>> device.disconnect()
>>> device.is_connected()
False

どうでしょうか?そこまで難しくはないと思います。python が書ける人であれば execute() から返ってくる出力を正規表現で欲しい情報を取得し・・・など色々とやりたいことがイメージできるのではないでしょうか。

Unicon は上記だけではなく、Unicon だけで色々な機能を持っています。
下記は対向機器へ ping を実施した例です。詳細は Unicon のドキュメントも参照してみてください。

>>> device.ping('10.2.2.2')
[2019-02-09 11:15:33,472] +++ csr1000v-1: ping +++
ping
Protocol [ip]:
Target IP address: 10.2.2.2
Repeat count [5]:
Datagram size [100]:
Timeout in seconds [2]:
Extended commands [n]: n
Sweep range of sizes [n]: n
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 10.2.2.2, timeout is 2 seconds:
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/3 ms
csr1000v-1#
(snip)
>>>

今回紹介した中では、testbed.yaml の読み込みで Genie.init() という Genie のメソッドを使っていますが、ほとんどはコネクタの Unicon ライブラリの機能となり Genie の機能はほとんど使っていません。Unicon を使うことで、機器への接続に関して同じ形で異なる機器を扱うことが可能になります。また、Unicon では SSH だけでなく、もちろん Telnet も使えます。(上の例では全て Telnet ですね)

ちょっと難しいなと感じた方、ご心配なく。次回紹介する Genie CLI や今後紹介する Genie Harness というのを使えば、上でやった簡単な python コードでの機器への接続すらも書く必要がありません。

次回はコードいらずで Genie を使える Genie CLI を紹介します。

スポンサーリンク