実践ネット自動化スクリプト集

Pythonによるネットワーク機器の情報取得自動化:CLIパースから構造化データ活用の実践へ

Tags: Python, ネットワーク自動化, NAPALM, RESTCONF, CLIパース, 構造化データ

ネットワーク機器からの情報取得は、自動化において非常に重要なステップです。現在の設定や状態を正確に把握できなければ、その後の設定変更や監視、トラブルシューティングといった自動化タスクは成り立ちません。しかし、ネットワーク機器の情報取得には特有の難しさがあります。

ネットワーク機器からの情報取得における課題

従来のネットワーク機器からの情報取得の主流は、SSHやTelnet経由でCLIコマンドを実行し、そのテキスト出力をパースするという手法でした。Pythonでは、paramikonetmikoといったライブラリを使うことで、このCLIコマンド実行と出力取得を自動化できます。

しかし、CLI出力のパースにはいくつかの大きな課題があります。

  1. ベンダー・OSバージョン依存: コマンドの出力フォーマットは、ネットワーク機器のベンダーやOSのバージョンによって大きく異なります。同じ情報を得るコマンドでも、機器が変わればパースロジックを書き直す必要があります。
  2. フォーマット変更のリスク: OSのバージョンアップなどで、予告なく出力フォーマットが変更されることがあります。これにより、これまで正常に動作していたパーススクリプトが突然壊れてしまうリスクが常に伴います。
  3. 複雑なロジック: テーブル形式や階層構造を持つCLI出力を正確にパースするには、複雑な正規表現や文字列処理ロジックが必要になることが多く、スクリプトの可読性やメンテナンス性を損ないます。

Python開発やクラウドインフラ自動化の経験が豊富な方々にとって、この「非構造化データ(テキスト)のパース」は、他の領域ではあまり遭遇しない、ネットワーク自動化ならではの障壁となりがちです。Pythonの豊富なデータ処理スキルを活かそうにも、まず整形されていないCLI出力をプログラムで扱いやすい形式に変換する前処理に多くの労力が必要になります。

構造化データの利便性と取得手法

これらの課題を克服し、より効率的かつ堅牢にネットワーク機器から情報を取得するために、構造化データとして情報を取得するアプローチが注目されています。構造化データとは、JSONやXMLのように、人間だけでなくプログラムが容易に解釈・処理できる形式で構成されたデータのことです。

ネットワーク機器から構造化データを取得する主な手法には、以下のようなものがあります。

  1. NAPALM: 複数のベンダーやOSに対応し、共通のPythonメソッド(Getter)を通じて標準化された構造化データ(通常はJSON形式)を取得できるライブラリです。CLIコマンドの出力を内部的にパースして構造化データに変換してくれます。
  2. NETCONF/RESTCONF: ネットワーク機器の設定や状態をAPIとして扱うための標準プロトコルです。XML(NETCONF)やJSON(RESTCONF)などの構造化データ形式で情報を取得できます。機器側がこれらのプロトコルをサポートしている必要があります。
  3. ベンダー独自のAPI: 各ベンダーが提供するAPI(RESTful APIなど)を通じて、構造化データとして情報を取得できます。

これらの手法を用いることで、CLIパースの煩雑さから解放され、取得した情報を直接Pythonの辞書やリストとして扱えるようになります。これにより、データの処理や活用といった本来の自動化ロジックに集中できるようになります。

実践:NAPALMによる構造化データ取得

ここでは、NAPALMを使った構造化データ取得の基本的な例を示します。NAPALMは多くの主要ベンダーに対応しており、比較的容易に導入できるため、CLIパースからの脱却の第一歩として最適です。

NAPALMをインストールするには、pipを使います。特定のベンダー(例: Cisco IOS)に対応させる場合は、対応ドライバーも一緒にインストールします。

pip install napalm napalm-ios # 例: Cisco IOSXE/IOSに対応する場合

次に、NAPALMを使って機器に接続し、情報を取得するPythonスクリプトの例です。

import json
from napalm import get_network_driver
from napalm.base.exceptions import NapalmException

# 接続情報を定義
device_info = {
    'hostname': 'your_device_ip_or_hostname',
    'username': 'your_username',
    'password': 'your_password',
    'optional_args': {} # 必要に応じてポート番号などを指定 e.g., {'port': 22}
}

# 使用するドライバーを指定 (例: ios)
driver = get_network_driver('ios')

# デバイスに接続
device = None
try:
    print(f"Connecting to {device_info['hostname']}...")
    device = driver(**device_info)
    device.open()
    print("Connection successful.")

    # 例: デバイスのファクト情報を取得
    # get_facts() はベンダー共通のメソッドで、ホスト名、モデル、シリアル番号などの基本情報を取得します
    facts = device.get_facts()
    print("\n--- Device Facts ---")
    # 取得した情報はPythonの辞書形式です
    print(json.dumps(facts, indent=2))

    # 例: インターフェース情報を取得
    # get_interfaces() も共通メソッドで、各インターフェースの状態や統計情報を取得します
    interfaces = device.get_interfaces()
    print("\n--- Interface Status ---")
    print(json.dumps(interfaces, indent=2))

    # 他にも様々なGetterメソッドがあります (例: get_lldp_neighbors, get_arp_table, get_mac_address_tableなど)
    # get_network_driver('ios').getters を参照すると、サポートされているメソッドを確認できます。

except NapalmException as e:
    print(f"An error occurred: {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")
finally:
    # 接続を閉じることを忘れない
    if device and device.is_open():
        device.close()
        print("\nConnection closed.")

上記のスクリプトを実行するには、your_device_ip_or_hostname, your_username, your_password を実際の環境に合わせて修正してください。また、機器側のSSHアクセスが有効になっている必要があります。

この例からわかるように、get_facts()get_interfaces()のような標準化されたメソッドを呼び出すだけで、ネットワーク機器の種類に関わらず、決まった構造(JSON形式)で情報を取得できます。これにより、取得後のデータ処理ロジックを共通化しやすくなります。

実践:API(RESTCONF)による構造化データ取得

次に、API、特にRESTCONFを使った情報取得の例を示します。RESTCONFはHTTP(S)上で動作し、RESTfulなインターフェースを提供するため、Web開発の経験がある方には馴染みやすいかもしれません。

RESTCONFを利用するには、機器側でのRESTCONFの有効化や、認証設定(Basic認証、Token認証など)が必要です。ここではPythonのrequestsライブラリを使った基本的なGETリクエストの例を示します。

import requests
import json

# 機器のIPアドレスまたはホスト名
device_ip = 'your_device_ip_or_hostname'
# RESTCONFのポート番号 (通常は443/HTTPSまたは80/HTTP)
restconf_port = 443
# 認証情報
username = 'your_username'
password = 'your_password'

# RESTCONFのエンドポイントURLの基本部分
# ベンダーやOSによってパスは異なります。以下は一般的な例です。
# 例: Cisco IOS XEのNativeモデルの場合
# base_url = f"https://{device_ip}:{restconf_port}/restconf/data/Cisco-IOS-XE-native:native"
# 例: IEEE 802.3-LAG YANGモデルの場合
base_url = f"https://{device_ip}:{restconf_port}/restconf/data/ieee802-dot3-lag:lags"


# 取得したい情報に対応するパスを指定
# 例: すべてのLAGインターフェース情報を取得
target_path = "" # base_urlでパスを終端している場合は空文字列

url = f"{base_url}{target_path}"

# ヘッダーの設定 (Accept: 応答形式, Content-Type: リクエストボディ形式)
headers = {
    'Accept': 'application/yang-data+json', # JSON形式で応答を要求
    'Content-Type': 'application/yang-data+json'
}

# SSL証明書の検証を無効化 (検証を推奨しますが、テスト目的で一時的に無効化する場合)
# verify = False
verify = True # 通常はTrueにするか、証明書パスを指定

try:
    print(f"Fetching data from {url}...")
    # GETリクエストを送信 (Basic認証を使用)
    response = requests.get(url, auth=(username, password), headers=headers, verify=verify)

    # レスポンスステータスコードを確認
    response.raise_for_status() # 200以外のステータスコードは例外を発生させる

    print("Request successful.")
    # 取得したJSONデータを表示
    data = response.json()
    print("\n--- Received Data ---")
    print(json.dumps(data, indent=2))

except requests.exceptions.RequestException as e:
    print(f"An error occurred during the request: {e}")
except Exception as e:
    print(f"An unexpected error occurred: {e}")

この例では、requestsライブラリを使って指定したURLにGETリクエストを送っています。RESTCONFはYANGモデルに基づいてデータ構造を定義しており、URLパスもYANGモデルに準拠します。取得されるデータはJSON形式であり、NAPALMと同様にPythonの辞書やリストとして容易に扱えます。

API活用のメリットは、機器がサポートしていれば、より粒度の細かい情報取得や、設定変更といった操作も構造化されたデータで実行できる点です。ただし、YANGモデルや各ベンダーの実装に関する知識が必要になる場合があります。

取得したデータの活用と自動化への組み込み

構造化されたデータとしてネットワーク機器の情報が手に入れば、Pythonの強力なデータ処理能力を存分に活かせます。

これらの自動化タスクにおいて、構造化データで情報が取得できることは、スクリプト開発の効率と信頼性を飛躍的に向上させます。

まとめ

ネットワーク機器からの情報取得は、自動化の基礎でありながら、CLIパースの課題が障壁となることが少なくありませんでした。Pythonの高いスキルを持つインフラエンジニアの皆様にとって、この点は特にボトルネックとなりがちです。

NAPALMやRESTCONF/NETCONFといった手法を活用することで、ネットワーク機器から情報を構造化データとして効率的かつ堅牢に取得できるようになります。これにより、取得後のデータ処理や、取得した情報を活用した様々な自動化タスクの開発に集中できます。

ぜひ、お手元のネットワーク機器がNAPALMやAPIに対応しているか確認し、構造化データでの情報取得を自動化の第一歩として取り入れてみてください。Pythonスキルを活かして、ネットワーク運用のさらなる効率化を実現できるはずです。