らくがきちょう

なんとなく ~所属組織/団体とは無関係であり、個人の見解です~

netmiko で Cisco IOS へログインするサンプル

netmiko を使って Cisco IOSバイスへログインするサンプルをメモしておきます。 TELNET / SSH アクセスする対象には CML2 上の IOSv 15.9(3)M3 を利用しました。

netmiko のインストール

今回は venv 環境を作成し、そこに netmiko をインストールすることにしました。 まず venv 環境を作成します。

mkdir my-first-netmiko
cd my-first-netmiko
python3 -m venv venv
source venv/bin/activate

netmiko をインストールします。

python3 -m pip install netmiko

TELNET

TELNET するサンプルは以下の通りです。 TELNET する場合、device_type には cisco_ios_telnet を指定します (cisco_ios を指定すると TELNET では無く、SSH 接続しようとするので注意が必要です)。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios_telnet",
    "ip": "10.0.0.1",
    "username": "admin",
    "password": "password",
    "port": 23,
    "secret": "secret",
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

output = net_connect.send_command("show clock")
print(output)

net_connect.disconnect()

SSH (パスワード認証)

パスワード認証による SSH 接続のサンプルは以下の通りです。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios",
    "ip": "10.0.0.1",
    "username": "admin",
    "password": "password",
    "port": 22,
    "secret": "secret",
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

output = net_connect.send_command("show clock")
print(output)

net_connect.disconnect()

SSH (鍵認証)

鍵認証による SSH 接続のサンプルは以下の通りです。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios",
    "ip": "10.0.0.1",
    "username": "admin",
    "key_file": "~/.ssh/id_rsa",
    "port": 22,
    "secret": "secret",
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

output = net_connect.send_command("show clock")
print(output)

net_connect.disconnect()

設定変更

設定変更を行う場合は send_command を多用するのでは無く、send_config_set を利用することで簡単に設定変更出来ます。 send_config_set を使えば設定モードへの移行 (例えば configure termina) や、設定モードの解除なども自動的に実行してくれます。 以下の例では send_config_set を使いつつ、設定変更した内容を標準出力へ書き出しています。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios",
    "ip": "10.0.0.1",
    "username": "admin",
    "password": "password",
    "port": 22,
    "secret": "secret",
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

commands = [
    "interface GigabitEthernet0/1",
    "description TEST",
    " ip address 192.0.2.1 255.255.255.0",
    " no shutdown",
]
output = net_connect.send_config_set(commands)
print(output)

net_connect.disconnect()

show tech-support

show tech-support を実行する、以下のサンプルを用意したとします。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios",
    "ip": "10.0.0.1",
    "username": "admin",
    "password": "password",
    "port": 22,
    "secret": "secret",
    "fast_cli": False
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

output = net_connect.send_command("show tech-support")
print(output)

net_connect.disconnect()

しかし、これを実行すると今回の環境では以下のエラーになりました。

# ./5-show-tech-support.py
Traceback (most recent call last):
  File "/root/my-first-netmiko/./5-show-tech-support.py", line 19, in <module>
    output = net_connect.send_command("show tech-support")
  File "/root/my-first-netmiko/venv/lib/python3.9/site-packages/netmiko/utilities.py", line 500, in wrapper_decorator
    return func(self, *args, **kwargs)
  File "/root/my-first-netmiko/venv/lib/python3.9/site-packages/netmiko/base_connection.py", line 1535, in send_command
    raise IOError(
OSError: Search pattern never detected in send_command: IOSv\#

send_command を実行した場合のタイムアウト時間はデフォルトで 100 秒です。 fast_cli というパラメータはデフォルトで True ですが、これが True だと各種タイムアウト値が 0.1 倍されます。 今回の CML2 環境では show tech-support が完了するまでに 30 秒程度かかっているのですが、netmiko のタイムアウト値が 100 x 0.1 = 10 秒になっており、send_command が期待した文字列 (ホスト名) が返ってこない=タイムアウトしたと判断し、結果的に OSError: Search pattern never detected in send_command: IOSv エラーになっています。 この問題を解決するには以下のように fast_cliFalse に設定します。

#!/usr/bin/env python3

from netmiko import ConnectHandler

cisco_ios = {
    "device_type": "cisco_ios",
    "ip": "10.0.0.1",
    "username": "admin",
    "password": "password",
    "port": 22,
    "secret": "secret",
    "fast_cli": False
}

net_connect = ConnectHandler(**cisco_ios)
net_connect.enable()

net_connect.send_command("terminal length 0")

output = net_connect.send_command("show tech-support")
print(output)

net_connect.disconnect()

今回は fast_cliFalse に設定することで show tech-support を実行出来ましたが、更にタイムアウト時間を調整する必要がある場合は send_command の引数に delay_factor を設定し、タイムアウト値に係数を掛けるなど、追加の考慮を検討しなければならないケースもあるかもしれません。

参考

IOSv のコンフィグ

今回、CML2 上に作成した IOSv には以下を設定しました。 PUBLIC-KEY やアドレス、ルーティング設定などは自身の環境にあわせて差し替えます。

hostname IOSv
!
service timestamps debug datetime msec localtime
service timestamps log datetime msec localtime
!
enable secret secret
!
clock timezone JST +9
!
no ip domain-lookup
ip domain name example.local
!
aaa new-model
username admin password password
!
interface GigabitEthernet0/0
 ip address 10.0.0.1 255.255.255.0
 no shutdown
!
ip route 0.0.0.0 0.0.0.0 10.0.0.254
!
ip ssh version 2
ip ssh pubkey-chain
  username admin
   key-string
(PUBLIC-KEY)
exit
!
no banner exec ^C
no banner incoming ^C
no banner login ^C
!
line vty 0 4
 transport input all
!
crypto key generate rsa modulus 2048
!
end