pyATSを触るためにCMLでtestbedファイルを用意してみた

#はじめに

pyATSとはCiscoが無償で提供しているマルチベンダー対応のテストフレームワークです。
pyATSでCMLに建てた機器にConnectするまでを触ってみました。
testbedファイルの作成や生成手段がわからず困っていたのでここに残しておきます。

#環境
・Windows 10 Enterprise
・WSL2 → Ubuntu 20.04 LTS
・CML Version: 2.2.1+build36

#構成図
かなり雑ですがやる気が消える前にアップしたかったのでスピード重視です。
![構成図.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1730261/4bdb0663-3609-676f-c83c-348dcaf57509.png)

#経緯
・手荒に扱える環境で試したかったのでCMLを対象にしました。
・pyATSやPythonの記事を見てなんとなく何かをやりたかった。
・Qiita投稿の初体験。

#やりたい事
1.pyATSで利用するtestbedファイルをCMLのAPIから払い出す。
2.払い出したファイルで接続できるのか試す。

#PC側の準備
pyATS_CMLファイルの中でvenvを使って仮想環境を用意する。
pyATSを使えるようにするため以下のコマンドを実行していきます。

```
$mkdir ~/pyats_CML
$cd ~/pyats_CML
$python3 -m venv .

$source bin/activate
$pip install --upgrade pip setuptools
$pip install pyats[full]

$mkdir work
```

以下のようなファイルが生成されてるはず。

```
(pyats_CML) pyats_CML hmasayuk$ ls
bin  include  lib  lib64  pyvenv.cfg  share work
```

#CML側の準備
続いてCML側の情報を取りに行きます。
CML側のAPI Documentationを利用します。
以下、ログイン後のGUI操作です。

![APIDOCUMENT.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1730261/ebc3aea5-b2ed-5ea2-3274-aa931ce0ae60.png)

![API.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1730261/a3b4aa49-2867-a965-c789-703c96e3080e.png)

` Try it out`を選択したら以下のコードが出るので、利用しているCMLのID/PWに置き換えましょう。
 >☞Executeで実行

```json
{
  "username": "change me",
  "password": "change me"
}
```


成功してれば` Server response `が ` 200`でCMLに対してのtokenが払い出されたはずです。
これでCMLのAPIが操作できるのでtestbedファイルを作成していきましょう。



` Labs `> ` [GET]/labs/{lab_id}/pyats_testbed`のAPIを使います。
![testbed_API.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1730261/d8717f60-3927-0d58-100d-5d25870af0a8.png)


` lab_id `はpyATSでConnectしたいラボのidを持ってきましょう。
※私はURLから` lab_id`は取得しました。URL以外からも引っ張れるかもですがわからなければ参考までに)

上記の操作も` Try it out`を選択してから行います。
 >☞Executeで実行

生成されたコードはこちら☟

<details><summary>testbed.yaml</summary><div>

```testbed.yaml
testbed:
  name: LABNAME
devices:
  terminal_server:
    os: linux
    type: linux
    credentials:
      default:
        username: change_me
        password: change_me
    connections:
      cli:
        protocol: ssh
        ip: CMLIP
  ubuntu-0:
    os: linux
    type: server
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n0/0
  iosv-0:
    os: ios
    type: router
    series: iosv
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n2/0
  server-0:
    os: linux
    type: server
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n4/0
  iosv-1:
    os: ios
    type: router
    series: iosv
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n1/0
  server-1:
    os: linux
    type: server
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n6/0
  desktop-0:
    os: linux
    type: server
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n9/0
  csr1000v-0:
    os: iosxe
    type: router
    series: csr1000v
    credentials:
      default:
        username: cisco
        password: cisco
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: telnet
        proxy: terminal_server
        command: open /ea18e3/n10/0
topology:
  ubuntu-0:
    interfaces:
      enp0s2:
        link: l0
        type: ethernet
      enp0s3:
        type: ethernet
  iosv-0:
    interfaces:
      Loopback0:
        type: loopback
      GigabitEthernet0/0:
        link: l2
        type: ethernet
      GigabitEthernet0/1:
        link: l3
        type: ethernet
      GigabitEthernet0/2:
        type: ethernet
      GigabitEthernet0/3:
        type: ethernet
  server-0:
    interfaces:
      eth0:
        link: l7
        type: ethernet
  iosv-1:
    interfaces:
      Loopback0:
        type: loopback
      GigabitEthernet0/0:
        link: l4
        type: ethernet
      GigabitEthernet0/1:
        link: l5
        type: ethernet
      GigabitEthernet0/2:
        type: ethernet
      GigabitEthernet0/3:
        type: ethernet
  server-1:
    interfaces:
      eth0:
        link: l6
        type: ethernet
  desktop-0:
    interfaces:
      eth0:
        link: l8
        type: ethernet
  csr1000v-0:
    interfaces:
      Loopback0:
        type: loopback
      GigabitEthernet1:
        link: l9
        type: ethernet
      GigabitEthernet2:
        type: ethernet
      GigabitEthernet3:
        type: ethernet
      GigabitEthernet4:
        type: ethernet
```
</div></details>

` change me`の部分を利用しているCMLの情報に書き換えたファイルを作業環境に持っていきます。

#動作確認
先ほど作成したtestbedファイルをworkへ格納。

```
$cd ~/pyats_CML/work
$touch testbed.yaml
$vi testbed.yaml 
###👆ここでtestbedファイルをコピペしてます。###

$ls
testbed.yaml
```
:::note info
ここではviと記載してますが、エディタならemacsでもなんでもいいです。
:::

実行してみましょう。

```
$ genie shell --testbed-file ~/pyats_CML/work/testbed.yaml
Welcome to pyATS Interactive Shell
==================================
Python 3.8.2 (default, Jul 16 2020, 14:00:26)
[GCC 9.3.0]

>>> from pyats.topology.loader import load
>>> testbed = load('/home/honda/pyats_CML/work/testbed.yaml')
-------------------------------------------------------------------------------
>>>
```
うごいてるっぽい！
ではこのままネットワーク情報を見ていきましょう。

```
>>> TEST = testbed.devices['iosv-0']   ###iosv-0を例として対象にしています。
>>> TEST.connect()

Connecting to console for iosv-0
Connected to terminalserver.
Escape character is '^]'.

iosv-0>
2021-07-20 12:26:52,407: %UNICON-INFO: +++ initializing handle +++
```
これで接続できましたね。
show コマンドを打てるか試してみます。

```
>>> TEST.parse('show version')

2021-07-20 12:33:42,629: %UNICON-INFO: +++ iosv-0 with alias 'a': executing command 'show version' +++
show version
Cisco IOS Software, IOSv Software (VIOS-ADVENTERPRISEK9-M), Version 15.9(3)M3, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2021 by Cisco Systems, Inc.
Compiled Wed 27-Jan-21 09:58 by prod_rel_team
```

取得完了！！無事に` show version`のコマンドの結果が見れますね。

#最後に
今回の取り組みでCMLのAPIやpyATSを調べるきっかけになった事でpyATSの可能性を感じることができました。
次はコンフィグ投入やpyATSでのテストコマンド使いたいと思います。

#参考先
[pyATS公式ドキュメント](https://developer.cisco.com/docs/pyats/)
[pyATS/genieを触ってみよう](https://qiita.com/snamon/items/6f5f67a0162d4dd6fb5e)