Pythonでシスコルータの型名とシリアル番号の収集を自動化してみた
ネットワークの自動化ネタのとして、シスコルータにログインして、型名とシリアル番号を自動的に収集してCSV形式でファイル保存するPythonスクリプトを試作してみました。 今回はPythonライブラリのnetmikoとtextfsm+ntc-templatesを利用しました。
やること
ネットワークのオペレーションを自動化するために、Pythonスクリプトの試作をしました。 シスコルータ(IOS、IOS XE、IOS XR、NX-OS)の型名とシリアル番号を収集して、CSV形式でファイルに出力します。
Pythonライブラリのnetmikoで、ルータにSSHでログインし、CLIでshow inventory
コマンドを実行して、型名とシリアル番号を取得します。
Pythonライブラリのtextfsm+ntc-templatesを利用して、コマンドの実行結果から必要な型名とシリアル番号を抽出します。
抽出した結果をCSV形式でファイルに保存します。
なぜやるのか
資産管理や保守登録の際、型名とシリアル番号の収集を、TeraTermからExcelにコピペしていたので、疲れました。 日々、ルータやスイッチが増設され、もっと楽にしたいと思ったので、自動化してみました。
仕組み
処理の流れは次の通りです。
- ルータ一覧(host.csv)を読み込み
- ルータ・スイッチへTelnet/SSHでログイン
- 各ルータでインベントリ取得コマンド(show inventory)を実行
- コマンド実行結果から型名とシリアル番号を抽出
- 型名とシリアル番号をCSV形式(inventory.csv)で保存
環境
今回、用意した環境は次の通りです。
項目 | 詳細 |
---|---|
Windwos 10 Pro, 1709 | Ubuntu 16.04でもOK |
Excel 2016 | ネットワークエンジニアの大好きな定番ソフト |
Python 3.6.3 | プログラミング言語と実行環境 |
Anaconda 5.0.1 | Pythonのオールインワンパッケージ |
netmiko 1.4.3 | Pythonライブラリ。ルータへTelnet/SSH用 |
textfsm 0.3.2 | Pythonライブラリ。コマンドの実行結果を解析し値を抽出 |
ntc-templates | testfsmの抽出テンプレート集 |
Cisco VIRL 1.3.296 | ルータのシミュレータ |
ディレクトリ構成
ディレクトリ構造は次の通りです。
ファイル名 | 用途 |
---|---|
hosts.csv | 入力ファイル。収集対象のルータのログインに必要なパラメータを記述したCSVファイル |
get_inventory.py | スクリプトファイル。型名とシリアル番号を自動取得 |
ntc-templates/templates/cisco_ios_show_inventory.template | 抽出テンプレートファイル。ntc-templatesを、git clone やzip形式でダウンロードし展開 |
inventory.csv | 出力ファイル。ホスト名、型名、シリアル番号が出力されたCSVファイル |
スクリプト(get_inventory.py)
自動化のスクリプトファイルは次の通りです。
import csv import textfsm import netmiko from pprint import pprint # インベントリ保存用変数 inventories = [] # TextFSMのテンプレート読み込み with open('ntc-templates/templates/cisco_ios_show_inventory.template') as f: fsm = textfsm.TextFSM(f) # ルータリストを読み込み with open('hosts.csv', 'r') as f: r = csv.DictReader(f) hosts = list(r) # ルータ単位でインベントリ取得して、CSVに保存する for host in hosts: print("collecting: %s" % host['hostname']) params = { 'device_type': host['device_type'], 'ip': host['ip'], 'username': host['username'], 'password': host['password'], 'secret': host['secret'], } # ルータにログイン conn = netmiko.ConnectHandler(**params) conn.enable() # IOS XRの場合、コマンドを変える if host['device_type'] == 'cisco_xr': # cisco_xr cmd = 'admin show inventory' else: # cisco_ios, cisco_xe, cisco_nxos cmd = 'show inventory' # インベントリ収集 output = conn.send_command(cmd) # TextFSMで、コマンド実行結果を変換 fsm.Reset() result = fsm.ParseText(output) pprint(result) # 各行の先頭にホスト名を付与 inventory = [[host['hostname']] + row for row in result] # インベントリを追記 inventories += inventory # CSV形式で保存する with open("inventory.csv", 'w') as f: w = csv.writer(f, lineterminator='\n') w.writerow(['HOSTNAME', 'NAME', 'DESCR', 'PID', 'VID', 'SN']) w.writerows(inventories)
抽出テンプレートファイル(cisco_ios_show_inventory.template)
cisco_ios_show_inventory.templateは、ntc-templatesをそのまま使用します。
Value NAME (.*) Value DESCR (.*) Value PID (([\S+]+|.*)) Value VID (.*) Value SN ([\w+\d+]+) Start ^NAME:\s+"${NAME}",\s+DESCR:\s+"${DESCR}" ^PID:\s+${PID}.*,.*VID:\s+${VID},.*SN:\s+${SN} -> Record ^PID:\s+,.*VID:\s+${VID},.*SN: -> Record ^PID:\s+${PID}.*,.*VID:\s+${VID},.*SN: -> Record ^PID:\s+,.*VID:\s+${VID},.*SN:\s+${SN} -> Record ^PID:\s+${PID}.*,.*VID:\s+${VID}.* ^PID:\s+,.*VID:\s+${VID}.* ^.*SN:\s+${SN} -> Record ^.*SN: -> Record
入力ファイル(hosts.csv)
型名とシリアル番号を収集する対象ルータの一覧です。 ホスト名やIPアドレス、ユーザ名、パスワードなど、ルータへのログインに必要な情報を記載します。
hostname,ip,device_type,username,password,secret nx-osv-1,172.16.1.105,cisco_nxos,cisco,cisco,cisco nx-osv-2,172.16.1.106,cisco_nxos,cisco,cisco,cisco iosv-1,172.16.1.101,cisco_ios,cisco,cisco,cisco iosv-2,172.16.1.102,cisco_ios,cisco,cisco,cisco iosxrv-1,172.16.1.103,cisco_xr,cisco,cisco,cisco iosxrv-2,172.16.1.104,cisco_xr,cisco,cisco,cisco csr1000v-1,172.16.1.99,cisco_xe,cisco,cisco,cisco csr1000v-2,172.16.1.100,cisco_xe,cisco,cisco,cisco
CSVファイルの各フィールドの用途は次の通りです。
フィールド名 | 用途 |
---|---|
hostname | CSVに出力する際に利用する識別子 |
ip | SSH/Telnet用の接続先のIPアドレス |
device_type | デバイスの識別子。機種を指定します |
username | ルータログイン時のユーザ名 |
password | ルータログイン時のパスワード |
secret | 特権モード(enableモード)のパスワード |
デバイスを識別するdevice_typeは次の通りです。
device_type名 | 対応OS |
---|---|
cisco_ios | Cisco IOS |
cisco_xe | Cisco IOS XE |
cisco_xr | Cisco IOS XR |
cisco_nxos | Cisco NX-OS |
cisco_ios_telnet | Cisco IOS、Telnet用 |
cisco_ios_serial | Cisco IOS、シリアル用。利用方法 |
cisco_asa | Cisco ASA |
対象ルータ
今回はCisco VIRLで仮想ルータを構築しました。 Cisco IOS、IOS XE、IOS XR、NX-OSの4パターンのルータを起動し、各機器のインベントリを収集します。
ホスト名 | OS |
---|---|
iosv-1/2 | Cisco NX-OS |
csr1000v-1/2 | Cisco IOS XE |
iosxrv-1/2 | Cisco IOS XR |
nx-osv-1/2 | Cisco NX-OS |
Cisco VIRLでは、マネジメントインタフェースが有効です。 今回は、マネジメントインタフェース経由でログインして、コマンドを実行します。
実行画面
python get_inventory.py
でスクリプトを実行します。
スクリプトを実行すると、各ルータにログインし、型名とシリアル番号を収集し、逐次表示します。
出力ファイル(inventory.csv)
スクリプトを実行すると、型名とシリアル番号の一覧(inventory.csv)がCSV形式で出力されます。
おわりに
60行程度のPythonスクリプトで、型名とシリアル番号の取得自動化ができました。 ntc-templatesを利用すると他のコマンドの実行結果をCSV形式で保存することも可能です。
みなさま、ネットワークオペレーションの自動化にチャレンジしてみましょう!