LoginSignup
10
7

More than 5 years have passed since last update.

Jupyter NotebookでCiscoルータコンフィグ生成ツールの作成

Last updated at Posted at 2017-11-26

Jupyter Notebookでipywidgetとjinja2を使い、Ciscoルータ(IOS)のコンフィグ生成ツールを作成します。

ipywidgetはJupyter Notebook上にテキストボックスやボタンを配置できるUIライブラリです。jinja2はpythonのテンプレートエンジンライブラリです。今回はコンフィグ作成に必要なパラメータをテキストボックスに入力し、ボタンを押すとCiscoルータのコンフィグ作成するようなツールを作ってみます。

早速ですが、Pythonコードと実行結果から確認していきます。

Pythonコード

python
from IPython.display import display, clear_output
from jinja2 import Template
from ipywidgets import Text, BoundedIntText, Button

global_template_txt = '''
hostname {{t_hostname}}
no ip domain-lookup
'''

recursive_template_txt = '''
int giga {{t_int_num}}
 no switchport
 ip address {{t_ip_address}} {{t_mask}}
 no shutdown
'''

global_template = Template(global_template_txt)
recursive_template = Template(recursive_template_txt)

tbox_hostname = Text (value='L3-SW1', description='hostname')
tbox_interface_num = BoundedIntText(value=0, min=0, max=5, step=1, description='Interface数:')
button = Button(description='generate config')

display(tbox_hostname)
display(tbox_interface_num)
display(button)

interface_boxes = []

def on_button_clicked(b) :
    global interface_boxes
    global_config = global_template.render(t_hostname = tbox_hostname.value)
    print(global_config)

    for i in range(tbox_interface_num.value) :
        recursive_config = recursive_template.render(t_int_num=interface_boxes[i].children[0].value,
                                                     t_ip_address=interface_boxes[i].children[1].value, 
                                                     t_mask=interface_boxes[i].children[2].value)
        print(recursive_config)

def on_value_change(change) :  
    global interface_boxes
    clear_output()
    display(tbox_hostname)
    display(tbox_interface_num)

    interface_boxes = []
    for i in range(change['new']) :
        interface_elements = [
            Text(value='1/0/1', description='I/F num'),
            Text(value='10.10.10.1',  description='I/F ip add'), 
            Text(value='255.255.255.0',  description='I/F mask')]
        interface_boxes.append(ipywidgets.Box(children = interface_elements))
        display(interface_boxes[i])

    display(button)
    button.on_click(on_button_clicked)

tbox_interface_num.observe(on_value_change, names='value')
button.on_click(on_button_clicked)

実行結果

初期画面

Screenshot from 2017-11-26 20-32-37.png

Interface数変更時

Screenshot from 2017-11-26 20-32-48.png

generate configボタン押下時

Screenshot from 2017-11-26 20-33-13.png

コンフィグの説明

実行順に見ていきます。

テンプレートの定義

python
global_template_txt = '''
hostname {{t_hostname}}
no ip domain-lookup
'''

recursive_template_txt = '''
int giga {{t_int_num}}
 no switchport
 ip address {{t_ip_address}} {{t_mask}}
 no shutdown
'''

global_template = Template(global_template_txt)
recursive_template = Template(recursive_template_txt)

ここでCiscoコンフィグのテンプレートを定義しています。グローバルコンフィグがglobal_templateに対応し、インターフェースコンフィグがrecursive_templateに対応しています。{{}}で囲まれた部分が変数になっており、あとから値を埋め込む箇所です。

初期画面の出力

python
tbox_hostname = Text (value='L3-SW1', description='hostname')
tbox_interface_num = BoundedIntText(value=0, min=0, max=5, step=1, description='Interface数:')
button = Button(description='generate config')

display(tbox_hostname)
display(tbox_interface_num)
display(button)

ここでホスト名とInterface数を入力するテキストボックス、及びコンフィグ作成ボタンを描画しています。

ipywidgetのイベント検出

python
tbox_interface_num.observe(on_value_change, names='value')
button.on_click(on_button_clicked)

一番最後の2行は、Interface数が変更された場合とボタンが押された場合に、それぞれon_value_change関数、on_button_clicked関数を呼び出すための記述です。

on_value_cange関数

python
def on_value_change(change) :  
    global interface_boxes
    clear_output()
    display(tbox_hostname)
    display(tbox_interface_num)

    interface_boxes = []
    for i in range(change['new']) :
        interface_elements = [
            Text(value='1/0/1', description='I/F num'),
            Text(value='10.10.10.1',  description='I/F ip add'), 
            Text(value='255.255.255.0',  description='I/F mask')]
        interface_boxes.append(ipywidgets.Box(children = interface_elements))
        display(interface_boxes[i])

    display(button)
    button.on_click(on_button_clicked)

on_value_change関数では、Interface数の変更に応じて画面に表示するインターフェースコンフィグ用のテキストボックス数を変えています。使うInterfaceが1つならテキストボックスも1行分、使うInterfaceが2つならテキストボックスも2行分出力させます。

on_button_clicked関数

python
def on_button_clicked(b) :
    global interface_boxes
    global_config = global_template.render(t_hostname = tbox_hostname.value)
    print(global_config)

    for i in range(tbox_interface_num.value) :
        recursive_config = recursive_template.render(t_int_num=interface_boxes[i].children[0].value,
                                                     t_ip_address=interface_boxes[i].children[1].value, 
                                                     t_mask=interface_boxes[i].children[2].value)
        print(recursive_config)

on_button_clicked関数では、コンフィグ作成・出力を行っています。コンフィグ作成ボタンが押された時に、global_templateは1回だけ、recursive_templateはInterface数分だけ繰り返し処理を行い、各テキストボックスの値をテンプレートの変数部分に埋め込んだあと、作成されたコンフィグを画面出力しています。

さいごに

正直なところ、自分が使う分にはipywidgetよりもテキストベースで直接パラメータ入力したほうが効率的です。
どちらかというと、プロジェクトやチーム内で共用するなど、他人に使ってもらうことを想定しています。

10
7
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
10
7