pyATS/Genieからコンソールサーバ経由でNW機器へログインする

# はじめに

Ciscoが公開しているPythonベースのテスト自動化ソリューション「pyATS/Genie」を使い、コンソールサーバ経由でNW機器へSSH/Telnetログインする方法をメモしておきます。

# テスト構成
pyATS/Genieから`Switch`へSSHログインする際、コンソールサーバのIPアドレス宛てに、TCPポート番号3001で接続する設定にしています。
またログイン時、コンソールサーバに設定したユーザ名/パスワード、スイッチに設定したenableパスワードが聞かれる設定にしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310082/5181cbbd-0e26-a21e-6c84-c979655b08e9.png)

# Testbed
今回作成したTestbedファイルは以下の通りです。コンソールサーバのユーザ名、パスワードを指定する点、ポート番号を指定する点以外は、通常のEthernet経由のSSHログインと同じ書き方です。

```yaml:testbed_console_ssh.yaml
testbed: 
  name: test_network
devices:
  Switch:
    os: ios
    type: switch
    series: catalyst
    credentials:
      default:
        username: <コンソールサーバのユーザ名>
        password: <コンソールサーバのパスワード>
      enable:
        password: <スイッチのパスワード>
    connections:
      defaults:
        class: unicon.Unicon
      a:
        protocol: ssh
        ip: 192.168.200.xx
        port: 3001
```

# Pythonコード
`Switch`にログインし、`FastEthernet0/20`を閉塞する例です。
重要なのは、ログイン時の`connect()`の引数として`prompt_recovery=True`を指定する点です。

コンソールサーバ経由でSSH/Telnetログインする場合、Enterキーの押下(改行コードを送信)しないとプロンプトが現れないケースがあります。
*CMLのBreakout Toolや、GNS3のコンソール宛てのTelnet接続時も同様だと思います。
*セイコーソリューションズ社のコンソールサーバのように、サーバ側で改行コード送信機能を持つものも存在します。

pyATS/GenieのPrompt Recovery機能は、通常のログイン処理でタイムアウトが発生した場合、デバイスのプロンプトが表示されるまで`\r`や`Ctrl-U`等のプロンプトリカバリーコマンドを順番に実行していきます。詳細は以下に記載されています。
[Unicon Plugins > Expect Abstraction Library > Prompt Recovery Feature](https://pubhub.devnetcloud.com/media/unicon/docs/developer_guide/eal.html#prompt-recovery-label)

```python:pyats1-1.py
from genie.testbed import load

testbed = load('testbed_console_ssh.yaml')   # Testbedを指定
device = testbed.devices['Switch']   # ログイン機器を指定

# init_config_commands=no logging console等の初期設定変更を無効化
device.connect(init_config_commands=[], prompt_recovery=True)

device.configure('''
    interface FastEthernet0/20
    no shutdown
''')
```

# 実行結果
パスワード入力完了後、60秒後にログイン処理がタイムアウトになり、その後`\r`コマンド実行でプロンプト`Switch#`が表示され、正しく設定変更されている事が分かります。
```
$ python pyats1-2.py 
2022-03-12 11:41:31,454: %UNICON-INFO: +++ Switch logfile /tmp/Switch-cli-20220312T114131453.log +++
2022-03-12 11:41:31,455: %UNICON-INFO: +++ Unicon plugin ios +++
Password: 
2022-03-12 11:41:31,649: %UNICON-INFO: +++ connection to spawn: ssh -l root 192.168.100.33 -p 3001, id: 140593851046320 +++
2022-03-12 11:41:31,650: %UNICON-INFO: connection to Switch
～(60秒後)ログイン処理のタイムアウト～
2022-03-12 11:42:31,714: %UNICON-WARNING: Timeout of 60 seconds has been reached.
～5種類のプロンプトリカバリーコマンドを10秒間隔で送信(最大で50秒待ち)～
Prompt Recovery has commenced. Total timeout occurs in 50 seconds.
2022-03-12 11:42:31,946: %UNICON-INFO: Sending prompt recovery command: b'\r'
～今回は最初の'\r'でログイン成功～
Switch#
2022-03-12 11:42:31,952: %UNICON-INFO: +++ initializing handle +++
2022-03-12 11:42:32,059: %UNICON-INFO: +++ Switch with via 'a': executing command 'term length 0' +++
term length 0
Switch#
2022-03-12 11:42:32,305: %UNICON-INFO: +++ Switch with via 'a': executing command 'term width 0' +++
term width 0
Switch#
2022-03-12 11:42:32,538: %UNICON-INFO: +++ Switch with via 'a': executing command 'show version' +++
show version
Cisco IOS Software, C3560 Software (C3560-IPSERVICESK9-M), Version 12.2(55)SE3, RELEASE SOFTWARE (fc1)
（省略）
Switch#
2022-03-12 11:42:35,972: %UNICON-INFO: +++ Switch with via 'a': configure +++
config term
Enter configuration commands, one per line.  End with CNTL/Z.
Switch(config)#
Switch(config)#    interface FastEthernet0/20
Switch(config-if)#    no shutdown
Switch(config-if)#end
Switch#
```