pyATS事始め


# 目的

Pythonは殆ど書いたことがないけど、テストに幾分かの自動化を試したい。
Ansible assertを使って簡単にテストを書いてみたけど処理が冗長になるのと
そもそもそういうツールじゃなくない？とモヤモヤしている。

## pyATS and Genie links.

* [Intoroduction - pyATS and Genie][1]
* [Requirements][2]
    * >= Python3.5
    * [Python virtual environment][3]
* [pyATS Documentation][4]
    * [RobotFramework Support][5]
* [Genie Documentation][6]
    * [RobotFramework Support][7]

[1]:https://developer.cisco.com/docs/pyats/
[2]:https://developer.cisco.com/docs/pyats/#!requirements
[3]:https://developer.cisco.com/docs/pyats/#!python-virtual-environment
[4]:https://developer.cisco.com/docs/pyats/api/
[5]:https://pubhub.devnetcloud.com/media/pyats/docs/robot/index.html
[6]:https://developer.cisco.com/docs/genie-docs/
[7]:https://pubhub.devnetcloud.com/media/pyats-packages/docs/genie/robot/index.html

## install pyATS and Genie with pip.

環境は Ubuntu Server 18.0.4, Python 3.6.8(venv)
Robot Framework(genie.lib.robot)も併せてインストール
インストールバージョンは記事作成時点で 19.7

```bash
$ pip install pyats genie genie.lib.robot ipython
```

## Genie写経1

GNS3のDavid-sanとCisco DevNetの Hank-sanの動画のコードを写経。

[Python, Genie and CSV Files = Easy Network Automation (DevNet)
](https://www.youtube.com/watch?v=23hPg88pZBo)

GenieでIOSのshow interfaces コマンドをパースしてInterfaceとMAC AddressをCSVファイルに出力する。

Genie parser は[Parsers List](https://developer.cisco.com/docs/genie-docs/) を参照

動画だと物理なのか Loopback Interfaceがなくて正常終了しているけど、こちらの環境はVIRLなので
普通にBuild ConfigurationするとLoも漏れなくついてきてしまい、Loopback InterfaceはMAC Addressを持たないので、そのまま実行すると KeyErrorになるのでKeyErrorの時はMAC Addressは設定しない。

```python

Traceback (most recent call last):
  File "interface_repory.py", line 29, in <module>
    'MAC Address': details['mac_address']}
KeyError: 'mac_address'
```

```python
#! /usr/bin/env python

from genie.conf import Genie
import csv

testbed = Genie.init('testbed.yaml')

device_interface_details = {}

for device in testbed.devices:
    testbed.devices[device].connect()
    interface_details = testbed.devices[device].parse('show interfaces')
    device_interface_details[device] =  interface_details

interface_file = "interfaces.csv"
report_fields = ["Device", "Interface", "MAC Address"]

with open(interface_file, 'w') as f:
    writer = csv.DictWriter(f, report_fields)
    writer.writeheader()

    for device, interfaces in device_interface_details.items():
        for interface, details in interfaces.items():
            try:
                writer.writerow(
                    {'Device': device,
                     'Interface': interface,
                     'MAC Address': details['mac_address']}
                )
            except KeyError:
                writer.writerow(
                    {'Device': device,
                     'Interface': interface,
                     'MAC Address': "None"}
                )
```

実行結果

```csv
$ cat interfaces.csv
Device,Interface,MAC Address
csr1000v-1,GigabitEthernet1,5e00.0000.0000
csr1000v-1,GigabitEthernet2,fa16.3e1c.a494
csr1000v-1,GigabitEthernet3,fa16.3e74.ae21
csr1000v-1,Loopback0,None
csr1000v-2,GigabitEthernet1,5e00.0001.0000
csr1000v-2,GigabitEthernet2,fa16.3eb2.a588
csr1000v-2,GigabitEthernet3,fa16.3eaf.7fb2
csr1000v-2,Loopback0,None
```

## testbed.yaml

```yaml

testbed:
    name: TestTopology.virl
    credentials:
        default:
            username: cisco
            password: cisco
        enable:
            password: cisco
devices:
    csr1000v-1:
        type: router
        os: iosxe
        connections:
            a:
                protocol: telnet
                ip: 192.168.30.60
                port: 17001
            vty:
                protocol: ssh
                ip: 192.168.30.100
    csr1000v-2:
        type: router
        os: iosxe
        connections:
            a:
                protocol: telnet
                ip: 192.168.30.60
                port: 17003
            vty:
                protocol: ssh
                ip: 192.168.30.101
topology:
    csr1000v-1:
        interfaces:
            GigabitEthernet1:
                ipv4: 172.16.1.100/24
                type: ethernet
            GigabitEthernet2:
                ipv4: 10.0.0.5/30
                type: ethernet
                link: link-1
            GigabitEthernet3:
                ipv4: 192.168.30.100/24
                type: ethernet
    csr1000v-2:
        interfaces:
            GigabitEthernet1:
                ipv4: 172.16.1.101/24
                type: ethernet
            GigabitEthernet2:
                ipv4: 10.0.0.6/30
                type: ethernet
                link: link-1
            GigabitEthernet3:
                ipv4: 192.168.30.101/24
                type: ethernet
```