4
2

More than 3 years have passed since last update.

Nornir3によるネットワーク自動化 ②設定変更編

Posted at

1. はじめに

前回の記事で、自動化フレームワーク「Nonir」のセットアップ方法、NW機器への接続、showコマンド実行と出力結果のパース等を行いました。

Nornir3によるネットワーク自動化 ①セットアップ、showコマンド実行編

今回はその続きで、同じくCisco IOS/NX-OS機器に対して設定変更、設定保存、事後のConfig反映確認を行ってみました。

2. セットアップ

2-1. Nornir + Plugins

Netmikoで設定変更と保存を行うためにnornir_netmikoプラグイン、Jinja2テンプレートからConfigを自動生成するためにnornir_jinja2プラグインを使います。
前回インストールしていなかった後者を追加インストールします。

pip install nornir_jinja2

3. Inventory / Configファイル

前回と同じものを使います。

4. Tasks (Pythonコード) と実行結果

4-1. 例1: Configファイルからの設定変更

簡単な例として、以下のNTPサーバ設定ファイルを流し込んでみます。

ntp_config.txt
ntp server 1.1.1.1 prefer
ntp server 2.2.2.2
nornir20.py
from nornir import InitNornir
from nornir.core.task import Task, Result
from nornir_utils.plugins.functions import print_result
from nornir_netmiko.tasks import netmiko_send_config

# 初期化
nr = InitNornir(config_file="config.yaml")

# タスクを実行し、result変数に格納
result = nr.run(
    # 実行結果に任意で名前を付けられる。指定しない場合はタスク名が使用される
    name="configure ntp server",
    # nornir_netmikoプラグイン内の関数を指定
    task=netmiko_send_config,
    # 設定ファイル(str型)
    config_file="ntp_config.txt"
    )

# 実行結果を表示
print_result(result)

実行結果

2台とも問題なく設定が行われました。複数回実行しても同じ結果だったため、Ansibleのような冪等性を担保する実装はされていないようです。

$ python nornir20.py
configure ntp server************************************************************
* iosvl2-0 ** changed : True ***************************************************
vvvv configure ntp server ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.
iosvl2-0(config)#ntp server 1.1.1.1 prefer
iosvl2-0(config)#ntp server 2.2.2.2
iosvl2-0(config)#end
iosvl2-0#
^^^^ END configure ntp server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* nxos-0 ** changed : True *****************************************************
vvvv configure ntp server ** changed : True vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.

nxos-0(config)# ntp server 1.1.1.1 prefer

nxos-0(config)# ntp server 2.2.2.2

nxos-0(config)# end

nxos-0# 
^^^^ END configure ntp server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

4-2. 例2: PythonコードによるConfig生成 + 設定変更

続いて、PythonコードでNTPサーバ設定を動的に生成し、設定変更を行ってみます。
タスクを定義する関数configure_ntp_serverの冒頭で、hostsファイルからリスト形式のNTPサーバアドレスを読み込み、1つ目の要素はpreferオプションあり、2つ目以降の要素はオプションなしでConfigに変換しています。
NTPサーバアドレスはhostsファイルではなくdefaultsファイルのdataキー内に定義していましたが、自動的にhostsファイルのdataキーの値として認識されるようです。

nornir21.py
from nornir import InitNornir
from nornir.core.task import Task, Result
from nornir_utils.plugins.functions import print_result
from nornir_netmiko.tasks import netmiko_send_config


def configure_ntp_server(task: Task) -> Result:
    # NTPサーバ設定Configの生成
    ntp_command = []
    num = 0
    for ip in nr.inventory.hosts[task.host.name]["ntp_server"]:
        ntp_command.append(f"ntp server {ip}{' prefer' if not num else ''}")
        num += 1

    data = task.run(
        # nornir_netmikoプラグイン内の設定変更用関数を指定
        task=netmiko_send_config,
        # 設定コマンド(list型)
        config_commands=ntp_command
        )

nr = InitNornir(config_file="config.yaml")

# 上記のカスタムタスクを実行し、結果をresultに格納
result = nr.run(
    task=configure_ntp_server
    )

# 実行結果を表示
print_result(result)

実行結果

例1と同様の結果になっています。

$ python nornir21.py
configure_ntp_server************************************************************
* iosvl2-0 ** changed : True ***************************************************
vvvv configure_ntp_server ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netmiko_send_config ** changed : True ------------------------------------- INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.
iosvl2-0(config)#ntp server 1.1.1.1 prefer
iosvl2-0(config)#ntp server 2.2.2.2
iosvl2-0(config)#end
iosvl2-0#
^^^^ END configure_ntp_server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* nxos-0 ** changed : True *****************************************************
vvvv configure_ntp_server ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- netmiko_send_config ** changed : True ------------------------------------- INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.

nxos-0(config)# ntp server 1.1.1.1 prefer

nxos-0(config)# ntp server 2.2.2.2

nxos-0(config)# end

nxos-0# 
^^^^ END configure_ntp_server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

4-3. 例3: Jinja2によるConfig生成 + 設定変更 + 保存 + テスト

最後に、Jinja2でテンプレートファイルとNTPサーバアドレスをレンダリングしてConfigを動的に生成し、設定変更を行ってみます。その後設定保存と、投入したコマンドがshow runの中に含まれているか確認します。

タスクは以下の1~5で構成されています。
(1) NTPサーバ設定Configの生成
(2) NTPサーバ設定変更
(3) 設定保存
(4) 事後のConfig取得
(5) 事後ConfigにNTPコマンドが存在するか確認

(1)はnornir_jinja2プラグイン、(2)~(4)はnornir_netmikoプラグイン、(5)は自作したvalidate_configを使っています。Pythonそのものを使っているので、カスタムのしやすさも魅力だと思います。

Jinja2テンプレートファイル

ntp_config.j2
ntp server {{ host["ntp_server"][0] }} prefer
{% for ip in host["ntp_server"][1:] %}
ntp server {{ ip }}
{% endfor %}
nornir23.py
from nornir import InitNornir
from nornir.core.task import Task, Result
from nornir_utils.plugins.functions import print_result
from nornir_netmiko.tasks import netmiko_send_command, netmiko_send_config, netmiko_save_config
from nornir_jinja2.plugins.tasks import template_file


# 事後のConfig内に、指定したコマンドが含まれているか判定
def validate_config(task: Task, intended_list: list, config: str) -> Result:
    result = ""
    for intended in intended_list:
        try:
            assert intended in config
            result += f"Assertion Success: '{intended}' exists in config\n"
        except AssertionError:
            result += f"Assertion Failure: '{intended}' not exists in config\n"
    return Result(host=task.host, result=result, changed=False)


def configure_ntp_server(task: Task) -> Result:
    data1 = task.run(
        # NTPサーバ設定Configの生成
        name="generate ntp config",
        # nornir_jinja2プラグイン内のJinja2テンプレートファイルからの設定変更用関数を指定
        task=template_file,
        # テンプレートファイル(str型)
        template="ntp_config.j2",
        path="./"
        )

    data2 = task.run(
        # NTPサーバ設定変更
        name="configure ntp server",
        # nornir_netmikoプラグイン内の設定変更用関数を指定
        task=netmiko_send_config,
        # 設定コマンド(list型)。1つ目のタスクで生成された改行付き文字列を、リスト形式に変換したもの
        config_commands=data1.result.splitlines()
        )

    data3 = task.run(
        # 設定保存
        name="save config",
        # nornir_netmikoプラグイン内の設定保存用関数を指定
        task=netmiko_save_config,
        cmd="copy run start",
        confirm="Destination filename",
        confirm_response="\n"
        )

    data4 = task.run(
        # 事後のConfig取得
        name="run show command",
        task=netmiko_send_command,
        enable=True,
        command_string="show run | inc ntp",
    )

    data5 = task.run(
        # 事後ConfigにNTPコマンドが存在するか確認
        name="confirm intended ntp commands exist",
        task=validate_config,
        intended_list=data1.result.splitlines(),
        config=data4.result
    )

nr = InitNornir(config_file="config.yaml")

# 上記のカスタムタスクを実行し、結果をresultに格納
result = nr.run(
    task=configure_ntp_server
    )

# 実行結果を表示
print_result(result)

実行結果

タスク1~5ともに問題なく完了し、最後でAssertion Successと表示されています。

$ python nornir23.py
configure_ntp_server************************************************************
* iosvl2-0 ** changed : True ***************************************************
vvvv configure_ntp_server ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- generate ntp config ** changed : False ------------------------------------ INFO
ntp server 1.1.1.1 prefer
ntp server 2.2.2.2

---- configure ntp server ** changed : True ------------------------------------ INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.
iosvl2-0(config)#ntp server 1.1.1.1 prefer
iosvl2-0(config)#ntp server 2.2.2.2
iosvl2-0(config)#end
iosvl2-0#
---- save config ** changed : True --------------------------------------------- INFO
copy run start
Destination filename [startup-config]? 
Building configuration...

---- run show command ** changed : False --------------------------------------- INFO
ntp server 1.1.1.1 prefer
ntp server 2.2.2.2
---- confirm intended ntp commands exist ** changed : False -------------------- INFO
Assertion Success: 'ntp server 1.1.1.1 prefer' exists in config
Assertion Success: 'ntp server 2.2.2.2' exists in config

^^^^ END configure_ntp_server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
* nxos-0 ** changed : True *****************************************************
vvvv configure_ntp_server ** changed : False vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv INFO
---- generate ntp config ** changed : False ------------------------------------ INFO
ntp server 1.1.1.1 prefer
ntp server 2.2.2.2

---- configure ntp server ** changed : True ------------------------------------ INFO
configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.

nxos-0(config)# ntp server 1.1.1.1 prefer

nxos-0(config)# ntp server 2.2.2.2

nxos-0(config)# end

nxos-0# 
---- save config ** changed : True --------------------------------------------- INFO
copy run start


---- run show command ** changed : False --------------------------------------- INFO
ntp server 1.1.1.1 prefer
ntp server 2.2.2.2

---- confirm intended ntp commands exist ** changed : False -------------------- INFO
Assertion Success: 'ntp server 1.1.1.1 prefer' exists in config
Assertion Success: 'ntp server 2.2.2.2' exists in config

^^^^ END configure_ntp_server ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

最後に

他の強力な自動化ツールであるAnsibleでは、冪等性が担保されていたり、独自のJinja2フィルターがあったりするため、同様の機能まで作りこむとなると大変かと思います。ネットワーク作業で、冪等性を気にする必要が無ければ、Nornirも有効なツールかと思います。

追加参考URL

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2