netmikoを使ってNW機器へSSHアクセス


概要

 netmikoを使ってNW機器にSSHアクセスしてみました。NW機器はどこのご家庭にでもあるCisco891を利用しています。
 netmikoのインストールからshow runコマンドを実行するところまでを、流れに沿って記載していきます。
 

実行環境

バージョン

 Pythonバージョン:3.6
 VSCodeバージョン:1.37.0

フォルダ構成

C:
┗ Python36Project
 ┗ ParamikoTest
  ┣ .vscode\
  ┃ ┣ launch.json
  ┃ ┗ settings.json
  ┣ netmikoTest(仮想環境フォルダ)
  ┃ ┣色々… 
  ┗ SourceFiles\
    ┣ netmikoTest.py
    ┗ netmikoTest2.py

※仮想咸鏡配下にPythonファイルを置いていないのは、Pythonファイルを仮想環境配下に置くとデバッグがうまく動かないことがあるからです。(2019年8月現在)
 ちなみにプロジェクト名がParamikoTestなのは、もともとParamikoでいろいろやろうとしていたからです。

netmikoのインストール

 まずは以下の通りpipでnetmikoをインストールします。
pip install netmiko
 ※Ctrl+@でターミナルを立ち上げると自動で仮想環境をアクティベートしてくれるので便利ですよね。

SSHでアクセスしてみる

 以下の通り記載して実行すると、SSHでアクセスしてshow run結果を取得できます。

netmikoTest.py
import netmiko

#デバイス情報の記載
device = {
    'device_type':'cisco_ios',
    'ip':'IPアドレス',
    'username':'アカウント',
    'password':'ログインパスワード',
    'secret':'特権パスワード',
}

#コマンドの実行
with netmiko.ConnectHandler(**device) as con:
    con.enable()
    output = con.send_command("show run")
    print(output)

 初めに、SSHするNW機器の情報を辞書形式で記載します。device_typeを指定してあげることで、そのNW機器に適したSSHコネクションのオブジェクトを生成するようです。Cisco891は当然IOSなのでcisco_iosを指定してあげます。
※NW機器の種別を自動で判別してくれるdevice_typeもあるみたいですね。

 そのほかに対応している(対応していそうな)NW機器はutilities.pyに記載されています。netmikoで実装を考える前に一度こちらを確認したほうがよさそうです。

 その後、netmiko.ConnectHandler()にデバイス情報を渡すとSSHコネクションのオブジェクトを取得できます。
 コネクションをenable()で有効化し、send_command()でNW機器にコマンドを送信すると、戻り値としてコマンドの実行結果が手に入ります。

 コネクションは最後にdisconnect()だかcleanup()だかで解放してあげないといけないみたいですが、GitHubからbase_connectionクラスを見ると、withが使える実装だったのでwithを使ってみました。__exit__()内でdisconnect()が呼ばれ、その中でcleanup()が呼ばれているので、withを使えば事後処理は問題なさそうです。

おまけ(Teratermライクにしてみた)

netmikoTest2.py
import netmiko

device = {
    'device_type':'cisco_ios',
    'ip':'IPアドレス',
    'username':'アカウント',
    'password':'ログインパスワード',
    'secret':'特権パスワード',
}

with netmiko.ConnectHandler(**device) as con:
    con.enable()
    while True:
        prompt = con.find_prompt()
        command = input(prompt)
        if(command == ''):
            continue
        elif (command == 'exit'):
            break
        else:
            output = con.send_command(command)
            print(output)

 簡易的なターミナルみたいにしてみました。
 whileの無限ループでコマンドを受け付けます。find_prompt()でプロンプトの文字列を取得できるようなので、その値をinput()に渡してあげています。exitと打ち込むと、コネクションを切断します。
 なぜかexitコマンドをそのまま渡すと、結果が返ってこないため、無理やり分岐させています。(本来なら省略コマンドも考慮すべきですが今回は無視します)
 同様にconf t等でモードを切り替えるとsend_command()から結果が返ってきません。おそらくプロンプトが変わるからなのではないかと思っていますが、ターミナルを作成することが目的ではないので詳細は調べていません。

終わりに

 一度paramikoで同様のプログラムを組もうと試みましたが、うまくログインすらできませんでした。netmikoを使えばわずか数行でSSHアクセスするプログラムが作成できてかなり便利です。対応するNW機器も多く、その気になれば自分で拡張もできそうなので、今後の期待も大ですね。
 次回は、netmikoとTextFSMを連携させて、NW機器の情報をフォーマットして出力みようと思います。