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

Pythonとncclientで始めるNETConfネットワーク自動化入門

Tags: Python, ncclient, NETConf, ネットワーク自動化, API連携

はじめに

ネットワーク機器の自動化は、現代のインフラ運用において不可欠な要素となっています。多くのエンジニアがCLI操作の自動化から着手しますが、CLIの出力は不安定でパースが難しいという課題があります。より構造的で信頼性の高い自動化を実現するためには、ネットワーク機器が提供するAPIを活用することが有効です。

本記事では、Pythonを用いてネットワーク機器のAPIを操作する手法として、NETConfプロトコルに焦点を当てます。特に、PythonでNETConfクライアントを実装するためのデファクトスタンダードライブラリである ncclient を使用した基本的なネットワーク自動化の方法について解説します。

CLIベースの自動化経験はあるものの、NETConfやAPI操作はこれからというシステムエンジニア・インフラエンジニアの皆様に向けて、ncclient の導入から基本的な操作までを実践的なコード例とともにご紹介します。

なぜNETConfなのか? API自動化の利点

従来のCLI操作によるネットワーク自動化は、show running-config のようなコマンドを実行し、そのテキスト出力を正規表現などでパースして必要な情報を抽出したり、設定コマンドのシーケンスを送信したりする方法が主流でした。しかし、この方法は以下のような課題を抱えています。

これに対し、NETConfのようなAPIを用いた自動化は、これらの課題を解決する手段となります。

NETConfは、SSH上で動作し、TCPポート830を使用するのが一般的です(SSHデフォルトポートである22を使用する場合もあります)。クライアント(自動化スクリプト)とサーバー(ネットワーク機器)間でRPC(Remote Procedure Call)メッセージを交換することで、機器の操作を行います。

ncclientの導入

ncclient はPythonでNETConfクライアントを実装するためのライブラリです。pipを使って簡単にインストールできます。

pip install ncclient lxml

lxml はXMLデータを効率的に扱うためのライブラリで、ncclient が依存しているため一緒にインストールします。

ncclientを使った基本的な接続

ネットワーク機器への接続は、ホスト名またはIPアドレス、ユーザー名、パスワード(またはSSHキー)を指定して行います。

import logging
from ncclient import manager

# ログ設定 (デバッグ情報を表示する場合)
# logging.basicConfig(level=logging.DEBUG)

def connect_netconf(host, port, user, password):
    """
    指定された情報でNETConfセッションを確立します。

    Args:
        host (str): 接続先ネットワーク機器のホスト名またはIPアドレス。
        port (int): NETConfポート番号 (通常 830)。
        user (str): 認証ユーザー名。
        password (str): 認証パスワード。

    Returns:
        ncclient.manager.Manager: 確立されたセッションマネージャーオブジェクト。
    """
    try:
        # SSHキーを使用する場合は password=None, key_filename='path/to/key' を指定
        conn = manager.connect(
            host=host,
            port=port,
            username=user,
            password=password,
            hostkey_verify=False, # 実際の本番環境ではhostkey_verify=Trueとし、既知のホスト設定を正しく行う必要があります
            device='generic' # 機器の種類に合わせて指定 (例: cisco_iosxe, juniper)。'generic'は広範な機器で動作しますが、特定の機能は制限される場合があります。
        )
        print(f"Successfully connected to {host}")
        return conn
    except Exception as e:
        print(f"Failed to connect to {host}: {e}")
        return None

# 使用例 (実際には適切な接続情報を設定してください)
if __name__ == "__main__":
    NETCONF_HOST = 'your_device_ip' # ネットワーク機器のIPアドレスまたはホスト名
    NETCONF_PORT = 830              # NETConfポート
    NETCONF_USER = 'your_username'  # ユーザー名
    NETCONF_PASSWORD = 'your_password' # パスワード (またはSSHキー)

    with connect_netconf(NETCONF_HOST, NETCONF_PORT, NETCONF_USER, NETCONF_PASSWORD) as m:
        if m:
            print("Connection capabilities:")
            for capability in m.server_capabilities:
                print(f"  - {capability}")
            # ここに他の操作を追加

    print("Connection closed.")

manager.connect() 関数で接続を確立します。with ステートメントを使用することで、セッション終了時に自動的に接続が閉じられるため便利です。hostkey_verify=False は検証を無効にしていますが、セキュリティ上、本番環境では必ず有効化し、既知のホスト情報を適切に管理してください。device パラメータは、特定のベンダーやOS向けに最適化されたドライバを選択できますが、generic は多くの機器で基本的な操作が可能です。

NETConf RPCの実行例: 設定の取得 (get-config)

NETConfの最も一般的な操作の一つは、機器の設定情報を取得することです。これには get-config RPCを使用します。取得したい設定情報全体、または特定の要素をフィルタリングして取得できます。

以下は、機器の running configuration 全体を取得する例です。

# 上記の接続確立コードに続けて実行

if m:
    print("\nGetting running configuration...")
    try:
        # datastore='running' で running configuration を指定
        # filter=None でフィルタリングなし (全取得)
        result = m.get_config(source='running')
        print("Received configuration (first 500 chars):")
        # XML形式の応答が得られる
        print(result.data_xml.strip()[:500] + "...")

        # 取得したXMLデータをパースして特定情報を抽出することも可能
        # 例: lxmlを使ってhostnameを取得 (XML構造は機器やYANGモデルによる)
        # from lxml import etree
        # root = etree.fromstring(result.data_xml.encode('utf-8'))
        # hostname_element = root.find('.//{*}hostname') # 適切なXPathを指定
        # if hostname_element is not None:
        #     print(f"Hostname: {hostname_element.text}")

    except Exception as e:
        print(f"Failed to get configuration: {e}")

m.get_config() メソッドを使用します。source='running' は、現在の稼働コンフィグを取得することを意味します。他にも、起動時コンフィグを示す startup(対応している機器の場合)や、編集中の候補コンフィグを示す candidate(対応している機器の場合)などがあります。

result.data_xml には、XML形式の応答データが含まれています。このXMLデータをPythonのXMLパースライブラリ(例: lxml)を使って解析することで、必要な設定値を構造的に取得できます。CLI出力のパースに比べて、形式が標準化されているため、より安定したデータ処理が可能です。

特定の情報だけを取得したい場合は、filter パラメータにXML形式のフィルタ条件を指定します。フィルタの書き方は、機器がサポートするYANGモデルの構造に依存します。

NETConf RPCの実行例: 設定の変更 (edit-config, commit)

NETConfを使って機器の設定を変更することも可能です。これには主に edit-configcommit RPCを使用します。多くの機器では、設定変更を直接 running config に適用するのではなく、まず候補設定(candidate datastore)に対して変更を加え、その後 commit RPCで running config に反映させるという2段階のプロセスを取ります。これは、設定変更の原子性を保ち、途中で問題が発生した場合に容易にロールバックできるようにするためです。

以下は、簡単な設定変更の例です(機器が candidate datastore をサポートしていることを前提とします)。

# 上記の接続確立コードに続けて実行

if m:
    print("\nEditing configuration...")
    # 設定変更内容をXML形式で定義
    # このXML構造は機器がサポートするYANGモデルに依存します
    # 例: Cisco IOS XE で hostname を変更する場合のYANGモデル(一部簡略化)に合わせたXML
    config_payload = """
<config>
  <native xmlns="http://cisco.com/ns/yang/Cisco-IOS-XE-native">
    <hostname>my-new-hostname</hostname>
  </native>
</config>
"""

    try:
        # candidate datastore に対して設定を編集
        # default_operation='merge' は既存設定とマージすることを意味します
        edit_result = m.edit_config(target='candidate', config=config_payload, default_operation='merge')
        print("Edit-config successful.")

        # commit RPC で候補設定を running config に反映
        commit_result = m.commit()
        print("Commit successful.")

        # ロールバック機能に対応している機器であれば、
        # m.discard_changes() で commit 前の変更を破棄
        # m.rollback() で直前の commit を元に戻す (要検証)

    except Exception as e:
        print(f"Failed to edit or commit configuration: {e}")

設定変更の内容は、config_payload という変数にXML形式で定義しています。このXMLの構造は、対象機器がNETConfで公開しているYANGデータモデルに厳密に従う必要があります。YANGモデルは、機器の機能を構造化し、NETConf経由で操作可能な要素や属性を定義しています。

m.edit_config() で、指定したターゲット (candidate) に対して設定変更を適用します。default_operation='merge' は、既存設定に今回指定した設定を追加・更新することを意味します。他にも replacedelete といった操作があります。

m.commit() で、candidate datastore に加えた変更を running datastore に反映させます。この時点で、設定変更が機器に実際に適用されます。

実践的な考慮事項

ncclient とNETConfを使った自動化を現場で利用する際には、いくつかの重要な考慮事項があります。

CLI自動化との使い分け

CLIベースの自動化とAPI(NETConf/RESTConfなど)による自動化は、どちらか一方だけが優れているというものではなく、状況に応じて使い分ける、あるいは組み合わせて使用するものです。

特に、新しい機器や仮想ネットワーク機能ではAPIが重視される傾向にあります。将来的にはAPIによる自動化が主流になっていくと考えられます。

まとめ

本記事では、Pythonライブラリ ncclient を使用して、NETConfプロトコルによるネットワーク機器の基本的な自動操作を行う方法について解説しました。

ncclient を利用することで、CLIのテキストパースに依存しない、構造的で信頼性の高いネットワーク自動化を実現できます。NETConfの get-configedit-configcommit といったRPCを適切に利用することで、機器の設定情報の取得や変更を安全に行うことが可能です。

NETConfとYANGデータモデルは、ネットワーク自動化の可能性を大きく広げます。この記事が、Pythonスキルを活かしてネットワーク自動化に取り組む皆様にとって、API自動化への第一歩を踏み出すきっかけとなれば幸いです。

今後は、より詳細なフィルタリング、YANGモデルの活用、エラー回復処理、そしてIaCツールとの連携など、実践的な応用例についてもご紹介していく予定です。