2014-10-29 02:17 PM
Nexus は古いバージョンでなければ Python というスクリプト言語を利用することができます。
Python を使うことで
- 複雑な処理をする新しいコマンド
- 定期的な処理を繰り返すデーモン
を簡単に作成することができます。
ここでは以下のドキュメントの障害を防ぐためのコマンドやデーモンを作成することを通して作り方を紹介したいと思います。
N5K: VPC+, Fex 環境で Unknown Unicast が Flooding されない場合がある
https://supportforums.cisco.com/ja/document/12331506
まず、上記ドキュメントに目を通してもらえば分かりますが障害は「Nexus5500 が FEX の先にあるホストのエントリを学習していれば発生しない」ということがわかります。
そのため、ここでは「dynamic に学習した FEX のエントリを static に変換する」コマンドと、それを自動で行うデーモンを作成することとします。
バージョンや機種により異なりますが、今回使用する Nexus5500 の バージョン 6.0(2)N2(5) では
python FILE_NAME
と指定します。
今回はファイル名を d2s.py とし、それを bootflash 直下に保存してあるとします。 その場合は以下のようになります。
NEXUS# python d2s.py もしくは NEXUS# python bootflash:d2s.py
実はコマンドを作成するのは非常に簡単であり、pythonで「特定の処理を一回走らせて終わり」というような実装をすればほぼ問題無く使えます。
ここでは「dynamic に学習した FEX の MAC エントリを static にする」というコマンドを以下の様な手順で作成します
#出力例 """ NEXUS# show mac address-table dynamic Legend: * - primary entry, G - Gateway MAC, (R) - Routed MAC, O - Overlay MAC age - seconds since last seen,+ - primary entry using vPC Peer-Link VLAN MAC Address Type age Secure NTFY Ports/SWID.SSID.LID ---------+-----------------+--------+---------+------+----+------------------ * 120 547f.ee48.fbbc dynamic 0 F F Eth101/1/20 * 119 547f.ee48.fbbc dynamic 10 F F Eth101/1/19 * 118 547f.ee48.fbbc dynamic 20 F F Eth101/1/18 * 1 6c9c.ed45.ec14 dynamic 0 F F Eth1/25 * 1 6c9c.ed45.ec15 dynamic 0 F F Eth1/13 """ # 全体の流れ def dynamic2static(): show_mac = cisco.cli('show mac address-table dynamic')[1] lines = show_mac.split('\n') dynamic_entries_on_fex = filter(is_dynamic_learn_on_fex, lines) static_mac_commands = map(get_static_mac_command, dynamic_entries_on_fex) cisco.cli("conf t") for command in static_mac_commands: cisco.cli(command) # FEX で dynamic 学習しているエントリか判別 def is_dynamic_learn_on_fex(line): words = line.split() if(len(words) != 8): return False if(words[3] != 'dynamic'): return False num_of_slash = len(words[7].split('/')) - 1 return num_of_slash == 2 # static で学習させるコマンドを作成 def get_static_mac_command(line): words = line.split() vlan = words[1] mac = words[2] interface = words[7] return 'mac address-table static ' + mac + ' vlan ' + vlan + ' interface ' + interface
上記の dynamic2static() 関数を呼ぶように python プログラムを起動してやればコマンドのように動きます。
clear するコマンドもほぼ同じ動きです。
先の学習方法は「一度動かしたら終わり」というような場合に使います。watchdog のような定期的な監視をしたいといった場合は「ずっと動き続ける」プログラムが必要です。そのようなプログラムはデーモンと呼ばれています。
デーモンを作ることは簡単でループ処理の中で「スリープ」と「処理の実行」を繰り返すことで実現できます。例えば、先の dynamic エントリを static エントリに変換するデーモンでしたら、以下のように作れます。
def start_daemon(interval): while True: time.sleep(interval) dynamic2static()
本来はデーモンを停止する方法や、デーモンがコンソールを奪わないようにするための方法が必要です。
後者については thread を使ったり Nexus 自体の機能を使ったりすることで実現できますが、今回は割愛します。
今回のスクリプトは一つのファイルに様々な機能がのっています。そのため、1タイムの学習、デーモンとしての起動、static エントリの削除などを使い分ける必要があります。
一般的にはプログラムの起動時に「引数」と呼ばれるオプションをつけることで、上記を使い分けます。
例えば
NEXUS# python d2p.py learn
という起動方法の場合 learn が引数です。
これをプログラム側で読み取り、与えられた内容に沿って挙動をかえます。
def print_usage(): print('usage: python d2s.py <OPTION>') print('Options and arguments') print('help: show help message') print('learn: convert current dynamic mac entry to static entry on fex') print('daemon <INTERVAL_SEC>: periodically convert dynamic entry to static entry on fex') print('') if(__name__ == '__main__'): num_of_arg = len(sys.argv) if(num_of_arg == 1): print_usage() elif(num_of_arg == 2 and sys.argv[1] == 'learn'): dynamic2static() elif(num_of_arg == 2 and sys.argv[1] == 'clear'): clear_static() elif(num_of_arg == 2 and sys.argv[1] == 'help'): print_usage() elif(num_of_arg == 3 and sys.argv[1] == 'daemon'): interval = int(sys.argv[2]) start_daemon(interval) else: print('** SYNTAX ERROR **') print_usage()
事前に3つのエントリをFEXで動的に学習させています。
n5548_f09(config)# show mac address-table dynamic Legend: * - primary entry, G - Gateway MAC, (R) - Routed MAC, O - Overlay MAC age - seconds since last seen,+ - primary entry using vPC Peer-Link VLAN MAC Address Type age Secure NTFY Ports/SWID.SSID.LID ---------+-----------------+--------+---------+------+----+------------------ * 120 547f.ee48.fbbc dynamic 0 F F Eth101/1/20 * 119 547f.ee48.fbbc dynamic 10 F F Eth101/1/19 * 118 547f.ee48.fbbc dynamic 20 F F Eth101/1/18 * 1 6c9c.ed45.ec14 dynamic 0 F F Eth1/25 * 1 6c9c.ed45.ec15 dynamic 0 F F Eth1/13
このエントリを static に変換します。
n5548_f09(config)# python d2s.py learn
テーブルを見ると static になっていることがわかります。
n5548_f09(config)# show mac address-table static | inc Eth * 120 547f.ee48.fbbc static 20 F F Eth101/1/20 * 119 547f.ee48.fbbc static 30 F F Eth101/1/19 * 118 547f.ee48.fbbc static 40 F F Eth101/1/18
次にデーモンを使ってリアルタイムに dynamic エントリを static エントリに変換させます。チェックインターバルは5秒としています。
n5548_f09(config)# python d2s.py daemon 5
動的に学習するようにpingをN5Kに打ってやると、それが static になっていることがわかります。
n5548_f09(config)# show mac address-table static | inc Eth * 122 547f.ee48.fbbc static 0 F F Eth101/1/22 * 121 547f.ee48.fbbc static 0 F F Eth101/1/21 * 120 547f.ee48.fbbc static 20 F F Eth101/1/20 * 119 547f.ee48.fbbc static 30 F F Eth101/1/19 * 118 547f.ee48.fbbc static 40 F F Eth101/1/18
最後に static に学習しているエントリを消去します。
n5548_f09(config)# python d2s.py clear n5548_f09(config)# show mac address-table static | inc Eth n5548_f09(config)#
最後にプログラム全体を記載いたします。
#!/user/bin/python # coding: utf-8 import sys, time, cisco def is_dynamic_learn_on_fex(line): words = line.split() if(len(words) != 8): return False if(words[3] != 'dynamic'): return False num_of_slash = len(words[7].split('/')) - 1 return num_of_slash == 2 def is_static_learn_command_on_fex(line): words = line.split() if(len(words) != 8): return False if(words[2] != 'static'): return False num_of_slash = len(words[7].split('/')) - 1 return num_of_slash == 2 def get_static_mac_command(line): words = line.split() vlan = words[1] mac = words[2] interface = words[7] return 'mac address-table static ' + mac + ' vlan ' + vlan + ' interface ' + interface def get_no_static_mac_command(line): words = line.split() mac = words[3] vlan = words[5] interface = words[7] return 'no mac address-table static ' + mac + ' vlan ' + vlan + ' interface ' + interface def dynamic2static(): show_mac = cisco.cli('show mac address-table dynamic')[1] lines = show_mac.split('\n') dynamic_entries_on_fex = filter(is_dynamic_learn_on_fex, lines) static_mac_commands = map(get_static_mac_command, dynamic_entries_on_fex) cisco.cli("conf t") for command in static_mac_commands: cisco.cli(command) def clear_static(): show_run_static_mac = cisco.cli('show run | inc address-table')[1] lines = show_run_static_mac.split('\n') static_entries_on_fex = filter(is_static_learn_command_on_fex, lines) no_static_mac_commands = map(get_no_static_mac_command, static_entries_on_fex) cisco.cli("conf t") for command in no_static_mac_commands: cisco.cli(command) def start_daemon(interval): while True: time.sleep(interval) dynamic2static() def print_usage(): print('usage: python d2s.py <OPTION>') print('Options and arguments') print('help: show help message') print('learn: convert current dynamic mac entry to static entry on fex') print('daemon <INTERVAL_SEC>: periodically convert dynamic entry to static entry on fex') print('') if(__name__ == '__main__'): num_of_arg = len(sys.argv) if(num_of_arg == 1): print_usage() elif(num_of_arg == 2 and sys.argv[1] == 'learn'): dynamic2static() elif(num_of_arg == 2 and sys.argv[1] == 'clear'): clear_static() elif(num_of_arg == 2 and sys.argv[1] == 'help'): print_usage() elif(num_of_arg == 3 and sys.argv[1] == 'daemon'): interval = int(sys.argv[2]) start_daemon(interval) else: print('** SYNTAX ERROR **') print_usage()
検索バーにキーワード、フレーズ、または質問を入力し、お探しのものを見つけましょう
シスコ コミュニティをいち早く使いこなしていただけるよう役立つリンクをまとめました。みなさんのジャーニーがより良いものとなるようお手伝いします
下記より関連するコンテンツにアクセスできます