DevNet Sandbox を使って pyATS/XPRESSO を CML2 と始めよう

この記事はシスコの有志による Cisco Systems Japan Advent Calendar 2020 1枚目の 11 日目として投稿しています。

2020年版: https://qiita.com/advent-calendar/2020/cisco (<<<今年)
2020年版(2枚目): https://qiita.com/advent-calendar/2020/cisco2 (<<<今年)
2019年版: https://qiita.com/advent-calendar/2019/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2017年版: https://qiita.com/advent-calendar/2017/cisco

# はじめに

pyATS 開発チームに所属する東村(@tahigash3)です。今回は [Cisco](https://cisco.com) が開発しているネットワーク自動化ツール [pyATS](https://developer.cisco.com/pyats/) を始めるにあたって、便利な [DevNet Sandbox](https://developer.cisco.com/site/sandbox/) が用意されているので、そちらをご紹介したいと思います。

今年のアドベントカレンダー2枚目において、下記記事を書いているので、こちらも合わせてご覧ください。
- [pyATS と Python辞書/JSON が楽しくなる Dq(Data Query) を極める!!](https://qiita.com/tahigash/private/2776b00e97a416b98e3d)

過去の記事でも [pyATS](https://developer.cisco.com/pyats/) について書いているので、こちらも合わせて参照ください。
- [pyATS|Genieの隠れ必殺技Blitzを用いて高速自動化テスト作成](https://qiita.com/tahigash/items/fa00872a1ced946da23b)
- [pyATS/GenieとRobot Framework で簡単にマルチベンダーネットワークをチェックする](https://qiita.com/tahigash/items/ceb0809a4a9464c521b3)


本題の前によく間違われる二点についてシェアさせてください。
- [pyATS](https://developer.cisco.com/pyats/) は **py は小文字で残りは大文字**です。PyATS ではありません。
- [pyATS](https://developer.cisco.com/pyats/) の**読み方はパイエーティーエス**です。パイヤッツではありません。

# ネットワーク自動化を始めたい方の悩み

Cisco では DevNet を通じてネットワークプログラマビリティやAPIを使った自動化について情報発信をしているため、ネットワーク自動化に興味がある人は多いと思います。そういう中で、始めるにあたっての悩みは下記の２つがメインではないでしょうか。

**1. Python 環境構築 (Pythonや[pyATS](https://developer.cisco.com/pyats/)のインストール)**
**2. ネットワーク機器の準備**

**その2つを一気に解消し、pyATS を試す環境が手に入るのが DevNet Sandbox です。**
しかも [pyATS](https://developer.cisco.com/pyats/) チームが今年リリースした [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) という [pyATS](https://developer.cisco.com/pyats/) GUI ダッシュボードもセットアップされており、またネットワーク機器には [CML2 (VIRL2)](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) が Sandbox の中で動いています。なんともお得な Sandbox ですね！これは使うしかありません！しかも無料で使えるのです！

# pyATS の DevNet Sandbox を予約する

(以降は私のアカウント及び英語環境、MacOS上での手順になるため、環境の違いにより画面表示は異なる場合があるかもしれません。予めご了承ください。)

まずは [Sandbox - Cisco DevNet](https://developer.cisco.com/site/sandbox/) のページへアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/955e2abb-f579-c12c-b482-781f95371cee.png)
上のメニューから `Sandbox Catalog` をクリックします。

(どのアカウントでログインするか聞かれるので、Webex Teams, GitHub や Google などのアカウントでログインしてください。)

すると、Sandbox の一覧が表示されるので、左上のサーチボックスに `pyATS` と入れると検索結果が表示され、[pyATS](https://developer.cisco.com/pyats/) の Sandbox のみが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/683ebf1c-0e3e-0888-5520-a39eb3c40850.png)
この Sandbox は 予約(RESERVE) する必要があるため、`RESERVE` ボタンを押します。(デフォルトでは2時間の利用時間となっているため、最大の6時間に変更しています。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/7dfa6c94-ed6c-86ba-a2f8-adb9bc685434.png)
すると、画面が切り替わり右上に何分で Sandbox の準備が完了するか表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/5e314cc6-db37-3328-870d-3ba7d58b1569.png)
Sandbox のセットアップが完了すると、下記のようなメールが届きます。Sandbox へは Cisco AnyConnect を使って VPN 経由でアクセスするため、そのための情報が書かれています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/c81f05e7-f0e2-96d5-de13-83712984f43a.png)
次に Cisco AnyConnect を開いて、上のメールに書かれていた `Lab Network Address` を下記黒塗りされている箇所にコピペして、`Connect`をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/c6144838-3fc7-7869-e082-603acafdfee8.png)
次にユーザ名、パスワードを聞かれるので、こちらもメールに書かれていた `Username`/`Password` を入力して `OK` します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/432e43e6-96c6-2053-8b28-a8222e1a54f1.png)
**これで Sandbox への VPN 接続は完了です。**

# Cisco pyATS XPRESSO Sandbox の中身

それでは `Cisco pyATS XPRESSO Sandbox` の中身を見ていきましょう。上の少し書いた通り、この Sandbox には色々なものが入っています。ワクワクしますね！

| サーバ | アドレス | 用途 |
|:------|:--------|:----|
| Devbox | 10.10.20.50 | pyATS がインストールされた Linux サーバ |
| XPRESSO Server | 10.10.20.54 | pyATS GUI ダッシュボード |
| Cisco Modeling Labs Server | 10.10.20.161 | CML2 (VIRL2)

ネットワークエンジニアとしては、どのようなネットワーク構成が用意されているのか気になるところですよね。早速 https://10.10.20.161 へアクセスして [CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) 上でトポロジを確認してみましょう。(ログイン手順は割愛していますが、ログイン情報はサーバ及ネットワーク機器共に Sandbox のページ上で確認できます。また、[CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html)の操作は本題ではないため、簡略化していますがご理解ください)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/e5279bb0-e1d4-9597-4e8d-e7ea1ce4b012.png)

`Multi Platform Network` というトポロジが既に起動されているのがわかります。(赤枠の中の右上で緑色の四角に起動している台数が表示されています)

赤枠部分をクリックすると、より詳細が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/db27760d-5a47-8284-6da5-5672af899735.png)

この構成の中には、IOSXE, IOSXR, NXOS, ASA 等が含まれており、[pyATS](https://developer.cisco.com/pyats/) を始めるには十分な構成になっています。**ポイントとしては各ネットワーク機器からの線が `sandbox-backend` に集中していることが分かる通り、ここを経由して pyATS がインストールされている Devbox からアクセスできるような構成になっています。**

もちろん [CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) 上で好きなトポロジを作成して、そのトポロジに対して pyATS でアクセスすることも可能です。

# pyATS を Devbox から試す

それではついに [pyATS](https://developer.cisco.com/pyats/) を触っていきたいと思います。まずは SSH で Devbox へアクセスしてください。

私の MacOS の場合は下記のように iTerm2 (または Terminal) からアクセスできます。

```bash
$ ssh developer@10.10.20.50
developer@10.10.20.50's password:
(py3venv) [developer@devbox ~]$
```
Python をご存知の方であれば気づくかと思いますが、`(py3venv)` と表示されており、ログインと同時に Python 仮想環境が有効になっています。

`pyats version check` コマンドで [pyATS](https://developer.cisco.com/pyats/) のバージョンを確認します。

```bash
(py3venv) [developer@devbox ~]$ pyats version check
You are currently running pyATS version: 20.8
Python: 3.6.8 [64bit]

  Package                      Version
  ---------------------------- -------
  genie                        20.8
  genie.libs.clean             20.8.1
  genie.libs.conf              20.8
  genie.libs.filetransferutils 20.8
  genie.libs.health            20.8
  genie.libs.ops               20.8
  genie.libs.parser            20.8
  genie.libs.robot             20.8
  genie.libs.sdk               20.8.2
  genie.telemetry              20.8
  genie.trafficgen             20.8
  pyats                        20.8
  pyats.aereport               20.8
  pyats.aetest                 20.8
  pyats.async                  20.8
  pyats.connections            20.8
  pyats.contrib                20.8
  pyats.datastructures         20.8
  pyats.easypy                 20.8
  pyats.kleenex                20.8.2
  pyats.log                    20.8
  pyats.reporter               20.8
  pyats.results                20.8
  pyats.robot                  20.8
  pyats.tcl                    20.8
  pyats.topology               20.8
  pyats.utils                  20.8
  unicon                       20.8.1
  unicon.plugins               20.8.1


(py3venv) [developer@devbox ~]$
```
本日現在では `20.10` (2020年10月リリース) が最新のため、`pyats version update` コマンドでバージョンアップしておきましょう。

```bash
(py3venv) [developer@devbox ~]$ pyats version update
Checking your current environment...


The following packages will be removed:

  Package                      Version
  ---------------------------- -------
  genie                        20.8
  genie.libs.clean             20.8.1
  genie.libs.conf              20.8
  genie.libs.filetransferutils 20.8
  genie.libs.health            20.8
  genie.libs.ops               20.8
  genie.libs.parser            20.8
  genie.libs.robot             20.8
  genie.libs.sdk               20.8.2
  genie.telemetry              20.8
  genie.trafficgen             20.8
  pyats                        20.8
  pyats.aereport               20.8
  pyats.aetest                 20.8
  pyats.async                  20.8
  pyats.connections            20.8
  pyats.contrib                20.8
  pyats.datastructures         20.8
  pyats.easypy                 20.8
  pyats.kleenex                20.8.2
  pyats.log                    20.8
  pyats.reporter               20.8
  pyats.results                20.8
  pyats.robot                  20.8
  pyats.tcl                    20.8
  pyats.topology               20.8
  pyats.utils                  20.8
  unicon                       20.8.1
  unicon.plugins               20.8.1


... and updated with:

  Package Version
  ------- -------
  ats     latest
  genie   latest
  unicon  latest


Are you sure to continue [y/N]? y
Uninstalling existing packages...
Installing new packages...

Done! Enjoy!

(py3venv) [developer@devbox ~]$
```
再度 `pyats version check` コマンドを打つとバージョンが上がっているのが確認できるかと思います。

```bash
(py3venv) [developer@devbox ~]$ pyats version check | grep currently
You are currently running pyATS version: 20.10
```
それでは現在どのフォルダにいるのか、そこにどんなファイルがあるのか `pwd` コマンドと `ls` コマンドで確認します。

```bash
(py3venv) [developer@devbox ~]$ pwd
/home/developer
(py3venv) [developer@devbox ~]$ ls
Desktop  Downloads  py3venv  shutdown.sh
(py3venv) [developer@devbox ~]$
```
`developer` ユーザのホームディレクトリにいることが分かります。`ls` コマンで確認できる `py3venv` フォルダへ `cd` コマンドで移動して再度 `ls` コマンドで確認します。

```bash
(py3venv) [developer@devbox ~]$ cd py3venv/
(py3venv) [developer@devbox py3venv]$ ls
bin  etc  include  lib  lib64  multi-platform-network.yaml  pyvenv.cfg  share
(py3venv) [developer@devbox py3venv]$
```
**[pyATS](https://developer.cisco.com/pyats/) ではネットワーク機器のアクセス情報を記載した testbed.yaml というファイルが必要になりますが、上で [CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) 上で確認したトポロジの testbed.yaml が既に用意されており、そのファイル名が `multi-platform-networ.yaml` になります。**

`pyats shell` コマンドに上記のファイルを渡して、機器への接続、パーサーの実行をやってみましょう。

```bash
(py3venv) [developer@devbox py3venv]$ pyats shell --testbed-file multi-platform-network.yaml
Welcome to pyATS Interactive Shell
==================================
Python 3.6.8 (default, Sep 14 2019, 14:33:46)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]

>>> from genie.testbed import load
>>> testbed = load('multi-platform-network.yaml')
-------------------------------------------------------------------------------
>>> device = testbed.devices['core-rtr01'] # testbed.yaml の中から `core-rtr01` デバイスを device 変数へ代入
>>> device.connect() # `core-rtr01` へ接続

2020-12-07 17:51:11,296: %UNICON-INFO: +++ core-rtr01 logfile /tmp/core-rtr01-cli-20201207T175111296.log +++

2020-12-07 17:51:11,296: %UNICON-INFO: +++ Unicon plugin iosxr/iosxrv +++

2020-12-07 17:51:11,300: %UNICON-INFO: connection via proxy terminal_server

2020-12-07 17:51:11,304: %UNICON-INFO: +++ connection to spawn: ssh 10.10.20.161, id: 139654848644488 +++

2020-12-07 17:51:11,306: %UNICON-INFO: connection to terminal_server
Warning: Permanently added '10.10.20.161' (RSA) to the list of known hosts.
developer@10.10.20.161's password:

****
CML^2 Console Server
****

tab completion works
list available nodes and node labels / IDs with "list"
it's also possible to do a "open /lab_1/n0/0" command

consoles>

2020-12-07 17:51:11,738: %UNICON-INFO: +++ initializing handle +++

2020-12-07 17:51:11,744: %UNICON-INFO: connection to core-rtr01

2020-12-07 17:51:11,745: %UNICON-INFO: Waiting for 5 seconds before attempting to connect..

2020-12-07 17:51:16,750: %UNICON-INFO: Trying to connect to prompt on device core-rtr01 ...
consoles> open /e65a3c/n3/0
Connecting to console for core-rtr01
Connected to terminalserver.
Escape character is '^]'.

RP/0/0/CPU0:core-rtr01#
RP/0/0/CPU0:core-rtr01#
RP/0/0/CPU0:core-rtr01#

2020-12-07 17:51:18,874: %UNICON-INFO: +++ initializing handle +++

2020-12-07 17:51:18,875: %UNICON-INFO: +++ core-rtr01: executing command 'terminal length 0' +++
terminal length 0
Tue Dec  8 01:51:17.876 UTC
RP/0/0/CPU0:core-rtr01#

2020-12-07 17:51:19,102: %UNICON-INFO: +++ core-rtr01: executing command 'terminal width 0' +++
terminal width 0
Tue Dec  8 01:51:18.096 UTC
RP/0/0/CPU0:core-rtr01#

2020-12-07 17:51:19,297: %UNICON-INFO: +++ core-rtr01: configure +++
configure terminal
Tue Dec  8 01:51:18.296 UTC
RP/0/0/CPU0:core-rtr01(config)#no logging console
RP/0/0/CPU0:core-rtr01(config)#logging console disable
RP/0/0/CPU0:core-rtr01(config)#line console
RP/0/0/CPU0:core-rtr01(config-line)#exec-timeout 0 0
RP/0/0/CPU0:core-rtr01(config-line)#absolute-timeout 0
RP/0/0/CPU0:core-rtr01(config-line)#session-timeout 0
RP/0/0/CPU0:core-rtr01(config-line)#line default
RP/0/0/CPU0:core-rtr01(config-line)#exec-timeout 0 0
RP/0/0/CPU0:core-rtr01(config-line)#absolute-timeout 0
RP/0/0/CPU0:core-rtr01(config-line)#session-timeout 0
RP/0/0/CPU0:core-rtr01(config-line)#commit
Tue Dec  8 01:51:19.776 UTC
RP/0/0/CPU0:core-rtr01(config-line)#end
RP/0/0/CPU0:core-rtr01#
>>>
```
ここまでで、`core-rtr01` へ接続できました。次はパーサー(Genie Parser)を実行してみます。

```bash
>>> device.parse('show ipv4 interface brief')

2020-12-07 17:54:34,791: %UNICON-INFO: +++ core-rtr01: executing command 'show ipv4 interface brief' +++
show ipv4 interface brief
Tue Dec  8 01:54:33.843 UTC

Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback0                      unassigned      Shutdown        Down     default
MgmtEth0/0/CPU0/0              10.10.20.173    Up              Up       Mgmt-intf
GigabitEthernet0/0/0/0         172.16.252.37   Up              Up       default
GigabitEthernet0/0/0/1         172.16.253.2    Up              Up       default
GigabitEthernet0/0/0/2         172.16.252.22   Up              Up       default
GigabitEthernet0/0/0/3         172.16.252.30   Up              Up       default
RP/0/0/CPU0:core-rtr01#
{'interface': {'Loopback0': {'ip_address': 'unassigned', 'interface_status': 'Shutdown', 'protocol_status': 'Down', 'vrf_name': 'default'}, 'GigabitEthernet0/0/0/0': {'ip_address': '172.16.252.37', 'interface_status': 'Up', 'protocol_status': 'Up', 'vrf_name': 'default'}, 'GigabitEthernet0/0/0/1': {'ip_address': '172.16.253.2', 'interface_status': 'Up', 'protocol_status': 'Up', 'vrf_name': 'default'}, 'GigabitEthernet0/0/0/2': {'ip_address': '172.16.252.22', 'interface_status': 'Up', 'protocol_status': 'Up', 'vrf_name': 'default'}, 'GigabitEthernet0/0/0/3': {'ip_address': '172.16.252.30', 'interface_status': 'Up', 'protocol_status': 'Up', 'vrf_name': 'default'}}}
>>>
```
CLI show コマンドの出力の後に波括弧`{}`で表示されているのが、パーサーが返した構造化データ(実際には Python の辞書)になります。

pyATS|Genie では便利な [Dq](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#dq) という機能があり、パーサーが返すデータは既に [Dq](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#dq) が使えるデータとなっており下記にように`.q.contains`などを付けることで特定の条件にマッチした情報のみ抜き出す、確認するといったことが非常に簡単にできます。

```bash
>>> output = device.parse('show ipv4 interface brief')

2020-12-07 17:58:35,587: %UNICON-INFO: +++ core-rtr01: executing command 'show ipv4 interface brief' +++
show ipv4 interface brief
Tue Dec  8 01:58:34.607 UTC

Interface                      IP-Address      Status          Protocol Vrf-Name
Loopback0                      unassigned      Shutdown        Down     default
MgmtEth0/0/CPU0/0              10.10.20.173    Up              Up       Mgmt-intf
GigabitEthernet0/0/0/0         172.16.252.37   Up              Up       default
GigabitEthernet0/0/0/1         172.16.253.2    Up              Up       default
GigabitEthernet0/0/0/2         172.16.252.22   Up              Up       default
GigabitEthernet0/0/0/3         172.16.252.30   Up              Up       default
RP/0/0/CPU0:core-rtr01#
>>> output.q.contains('Shutdown')
Dq(paths=[DictItem(path=('interface', 'Loopback0', 'interface_status'), value='Shutdown')])
```
上記は `Shutdown` というキーワードを含むインタフェースのみを表示してみました。簡単ですよね？ pyATS が用意するライブラリを使うことで簡単に効率よくネットワーク機器情報の取得、確認、特定の情報の抜き出しといった自動化に必要な操作が可能になります。

次に pyATS CLI (以前は Genie CLI と読んでいました)を使ってみます。Python を知らなくとも事前/事後のネットワーク機器の状態を取得し、差分の確認ができる便利な pyATS CLI コマンドです。

```bash
(py3venv) [developer@devbox py3venv]$ pyats learn ospf --testbed-file multi-platform-network.yaml --devices core-rtr01 core-rtr02 dist-rtr01 dist-rtr02 dist-sw01 dist-sw02
/home/developer/py3venv/bin/pyats:8: DeprecationWarning: Device inside-host01 'tacacs.username' is deprecated in the testbed YAML.  This key has been moved to device 'credentials'.
  sys.exit(main())
/home/developer/py3venv/bin/pyats:8: DeprecationWarning: Device inside-host01 'passwords.linux' is  deprecated in the testbed YAML.  Use 'credentials' instead.
  sys.exit(main())

Learning '['ospf']' on devices '['core-rtr01', 'core-rtr02', 'dist-rtr01', 'dist-rtr02', 'dist-sw01', 'dist-sw02']'
100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:13<00:00, 13.83s/it]
+==============================================================================+
| Genie Learn Summary for device core-rtr01                                    |
+==============================================================================+
|  Connected to core-rtr01                                                     |
|  -   Log: ./connection_core-rtr01.txt                                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxr_core-rtr01_ops.txt                          |
|  -  Device Console: ./ospf_iosxr_core-rtr01_console.txt                      |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device core-rtr02                                    |
+==============================================================================+
|  Connected to core-rtr02                                                     |
|  -   Log: ./connection_core-rtr02.txt                                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxr_core-rtr02_ops.txt                          |
|  -  Device Console: ./ospf_iosxr_core-rtr02_console.txt                      |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device dist-rtr01                                    |
+==============================================================================+
|  Connected to dist-rtr01                                                     |
|  -   Log: ./connection_dist-rtr01.txt                                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxe_dist-rtr01_ops.txt                          |
|  -  Device Console: ./ospf_iosxe_dist-rtr01_console.txt                      |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device dist-rtr02                                    |
+==============================================================================+
|  Connected to dist-rtr02                                                     |
|  -   Log: ./connection_dist-rtr02.txt                                        |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_iosxe_dist-rtr02_ops.txt                          |
|  -  Device Console: ./ospf_iosxe_dist-rtr02_console.txt                      |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device dist-sw01                                     |
+==============================================================================+
|  Connected to dist-sw01                                                      |
|  -   Log: ./connection_dist-sw01.txt                                         |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_nxos_dist-sw01_ops.txt                            |
|  -  Device Console: ./ospf_nxos_dist-sw01_console.txt                        |
|==============================================================================|


+==============================================================================+
| Genie Learn Summary for device dist-sw02                                     |
+==============================================================================+
|  Connected to dist-sw02                                                      |
|  -   Log: ./connection_dist-sw02.txt                                         |
|------------------------------------------------------------------------------|
|  Learnt feature 'ospf'                                                       |
|  -  Ops structure:  ./ospf_nxos_dist-sw02_ops.txt                            |
|  -  Device Console: ./ospf_nxos_dist-sw02_console.txt                        |
|==============================================================================|



(py3venv) [developer@devbox py3venv]$
```
上の例ではトポロジ上の IOSXE, IOSXR, NXOS 機器に対して OSPF の情報を学習(learn)するコマンドを実行しました。pyATS|Genie の `learn` では抽象化されたモデルでの情報取得をするため、上の `Ops structure` を見ていただくと違う OS からの情報でも同じ構造化データになっていることが確認できるかと思います。**Genie Opsモデルを利用して CLI でも IOSXE, IOSXR, NXOS 間の差を吸収し、同じように自動化ができる点も pyATS|Genie のメリットになります。**

# pyATS GUI ダッシュボード (XPRESSO)

長くなってきていますが、最後に pyATS チームが今年リリースをした XPRESSO (pyATS GUI ダッシュボード) を紹介させてください。

pyATS のために生まれた UI となっており、pyATS で扱うネットワーク機器の環境情報(testbed.yaml)や `Job` ファイルといったものが GUI で設定でき、また実行結果の表示や２つの実行結果間での差分確認をすることも可能です。ちなみに pyATS|Genie と同じく無料で利用できます。

簡単に [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) ができることを列挙してみました。これは全てではなく、一部です。

**- pyATS Job ファイルの実行及び結果の表示**
**- Job のプロファイル作成(同一Jobに対して異なる条件での実行を定義できる)**
**- 実行Python環境の切替**
**- Jenkins or Docker での pyATS Job 実行**
**- テストベッド環境のマネージメント及キューイング(Job実行時は使用中となり、他のJobが該当テストベッドを使えない)**
**- Job のスケジュール実行**
**- ユーザ/グループによるアクセス権限**
**- XPRESSO REST API (pyATS Job 実行結果、テストベッド情報の取得など)**
**- 実行結果間での差分表示(Diff)**

詳細はドキュメントを参照してください。[pyATS Dashboard: XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso)
[XPRESS](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso)のインストールステップは GitHub のレポジトリの README からも確認できます。[xpresso repository on GitHub](https://github.com/CiscoTestAutomation/xpresso)

それでは [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) にアクセスしてみましょう。http://10.10.20.54 へアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/0fb684b2-4d68-b701-31c7-ca23c767b200.png)
このページはスクロールすることができ、[XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) の概要が紹介されているので、見てみて下さい。右上の `Login` からログインします。（認証情報は Sandbox 上の情報から確認して下さい。)

ログインすると、既にいくつかの実行結果があり、どのように結果が表示されるのか、確認できるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/8b80a824-b3db-7846-f35c-6be4256a4443.png)
ではログを見て見ましょう。一番下の `REQ0000001` をクリックしてみてください。すると次の画面では実行されたジョブのサマリーが表示されるので、再度リクエスト番号 `REQ000001` をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/d55bf7bb-8835-0409-90de-910de9c2e4c1.png)
すると次の画面ではどのような内容が実行されたのかが確認できる画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/3900dc83-b666-289c-48a2-307e5f2a7815.png)
左側の項目をクリックすると、その項目に対応するネットワーク機器のログが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/b43016f9-fe86-2d85-4c5b-4fdaebce74d8.png)

**ネットワークエンジニアなら、ネットワーク機器のログがステップ毎に分かり易く確認できるのは便利ですよね。もちろんログ内の検索やログのダウンロードも可能です。**

最後に `XPRESSO` 上で用意されているジョブを実行してみましょう。
左上の三本線のようなアイコンをクリックしてメニューを開き、`Jobs` をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/c95a9646-5884-b9c6-6b7a-2d6f9d1ce047.png)
次に実行したいジョブ(ここでは`Interface-CRC-Checker`)の右側のマウスを持っていくと、アイコンが表示されるので、再生ボタン(実行ボタン)を押すと、ジョブの設定画面に移ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/417d3ac2-e3fc-bf0e-925b-9ca5cb391a5d.png)
この画面ではジョブの優先度や最大実行時間などを指定できますが、今回は特に変更せず `Submit` を押して実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/18939316-6923-ef2a-5daf-3578a568ca72.png)
実行されると REQ番号 が発行され、右上のステータスが `PREPARING` -> `QUEUING` -> `RUNNING` と変更され、実行されていく様子が分かります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/695a6729-3e92-6198-79e1-8e19c3bb4438.png)
実行が完了すると下記のような画面になり、左下の REQ番号 をクリックすることで、前述と同じように実行結果の詳細を確認することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309712/125dda7b-9f07-bd18-9976-07c262f206cc.png)

# まとめ

今回は DevNet Sandbox を使って pyATS/XPRESSO を [CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) と一緒に使う方法を紹介しました。細かい部分までは紹介していませんが、DevNet Sandbox に用意された環境を利用して、簡単に pyATS 及び [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) が試せることが分かっていただけたのではないでしょうか。

- pyATS には便利に始められる Devnet Sandbox がある
- しかも [CML2](https://www.cisco.com/c/en/us/products/cloud-systems-management/modeling-labs/index.html) も一緒に使える
- [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) (pyATS GUI ダッシュボード) にも触れる
- git で色々なレポジトリをクローンしたり、pip でパッケージを入れると楽しむ可能性は無限大

最後に pyATS/Genie または [XPRESSO](https://developer.cisco.com/docs/pyats/#!pyats-dashboard-xpresso) に関する問い合わせ方法ですが、英語となってしまいますが、pyats-support-ext(at)cisco.com へ送っていただけると、pyATS チームの方で対応する形となります。日本語のサポートは現時点では用意されていませんが、Twitter で呟いていただくと、私のアカウント @tahigash3 が反応するかもしれません。

また、Webex Teams でも [pyATS community](https://eurl.io/#r18UzrQVr) スペースがあり、社内外のユーザにて活発に意見交換がされているので、是非ご参加ください。参加リンク : https://eurl.io/#r18UzrQVr

# 参考リンク
- [pyATS Document](https://developer.cisco.com/docs/pyats/api/)
- [Genie Document](https://developer.cisco.com/docs/genie-docs/)
  - [Genie CLI - Genie Run](https://pubhub.devnetcloud.com/media/genie-docs/docs/cli/genie_run.html)
  - [Genie API Browser](https://pubhub.devnetcloud.com/media/genie-feature-browser/docs/#/)
  - [Genie Useful Libraries](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#)
    - [Dq](https://pubhub.devnetcloud.com/media/genie-docs/docs/userguide/utils/index.html#dq)
  - [Genie Parser GitHub](https://github.com/CiscoTestAutomation/genieparser)
  - [Genie Libs GitHub](https://github.com/CiscoTestAutomation/genielibs)
- [XPRESSO Document](https://developer.cisco.com/docs/xpresso/)
    - [XPRESSO GitHub](https://github.com/CiscoTestAutomation/xpresso)
- [pyATS community on webex teams](https://eurl.io/#r18UzrQVr)

# 免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。