kooshinlab

現役ネットワークエンジニアが、ネットワーク運用で必要になった技術の記事を書くブログです。

Pythonでシスコルータの型名とシリアル番号の収集を自動化してみた

ネットワークの自動化ネタのとして、シスコルータにログインして、型名とシリアル番号を自動的に収集してCSV形式でファイル保存するPythonスクリプトを試作してみました。 今回はPythonライブラリのnetmikotextfsm+ntc-templatesを利用しました。

f:id:KOOSHIN:20171206223220p:plain
シスコルータの型名とシリアル番号の一覧(CSV形式)

やること

ネットワークのオペレーションを自動化するために、Pythonスクリプトの試作をしました。 シスコルータ(IOSIOS XE、IOS XR、NX-OS)の型名とシリアル番号を収集して、CSV形式でファイルに出力します。

Pythonライブラリのnetmikoで、ルータにSSHでログインし、CLIshow inventoryコマンドを実行して、型名とシリアル番号を取得します。 Pythonライブラリのtextfsm+ntc-templatesを利用して、コマンドの実行結果から必要な型名とシリアル番号を抽出します。 抽出した結果をCSV形式でファイルに保存します。

なぜやるのか

資産管理や保守登録の際、型名とシリアル番号の収集を、TeraTermからExcelにコピペしていたので、疲れました。 日々、ルータやスイッチが増設され、もっと楽にしたいと思ったので、自動化してみました。

仕組み

処理の流れは次の通りです。

  1. ルータ一覧(host.csv)を読み込み
  2. ルータ・スイッチへTelnet/SSHでログイン
  3. 各ルータでインベントリ取得コマンド(show inventory)を実行
  4. コマンド実行結果から型名とシリアル番号を抽出
  5. 型名とシリアル番号をCSV形式(inventory.csv)で保存

f:id:KOOSHIN:20171206073058p:plain
仕組みの概要図

環境

今回、用意した環境は次の通りです。

項目 詳細
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アドレス、ユーザ名、パスワードなど、ルータへのログインに必要な情報を記載します。

f:id:KOOSHIN:20171206070101p:plain
対象ルータ一覧ファイル(hosts.csv

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 IOSTelnet
cisco_ios_serial Cisco IOS、シリアル用。利用方法
cisco_asa Cisco ASA

対象ルータ

今回はCisco VIRLで仮想ルータを構築しました。 Cisco IOSIOS 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では、マネジメントインタフェースが有効です。 今回は、マネジメントインタフェース経由でログインして、コマンドを実行します。

f:id:KOOSHIN:20171206222542p:plain
Cisco VIRLによる仮想ルータのシミュレーション環境

実行画面

python get_inventory.pyスクリプトを実行します。 スクリプトを実行すると、各ルータにログインし、型名とシリアル番号を収集し、逐次表示します。

f:id:KOOSHIN:20171206070610p:plain
実行画面

出力ファイル(inventory.csv

スクリプトを実行すると、型名とシリアル番号の一覧(inventory.csv)がCSV形式で出力されます。

f:id:KOOSHIN:20171206065949p:plain
型名とシリアル番号の一覧(CSV形式)

おわりに

60行程度のPythonスクリプトで、型名とシリアル番号の取得自動化ができました。 ntc-templatesを利用すると他のコマンドの実行結果をCSV形式で保存することも可能です。

みなさま、ネットワークオペレーションの自動化にチャレンジしてみましょう!