はじめに
Cisco IOS-XEの16.5から、ネットワーク機器内(On-Box)でPythonプログラミングができるようになりました。
本記事では、設定変更をトリガーにして、指定したshowコマンド一式を取得し、TFTPサーバに転送する例をご紹介します。
用意した環境
Cisco DevNet Sandbox環境 IOS XE on Catalyst 9000 Lab を使用しました。
今回はCatalyst9300を使用していますが、バージョン要件を満たすIOS-XEであれば問題ないと思います。
TFTPサーバは、Sandbox内に用意されていたCentOSを使いました。ほんと至れり尽くせりですね!
用途 | 機種 | バージョン | 備考 |
---|---|---|---|
検証対象機器(IOS-XE) | Catalyst9300-24UX | 16.8.1a | |
検証対象機器(ゲストシェル) | CentOS | 7.6.1810 | Python=2.7.5 |
TFTPサーバ | CentOS | 7.3.1611 |
TFTPサーバのセットアップ
以下の記事を参考にさせて頂きました。
TFTPサーバの構築(CentOS7)
TFTPサーバのアップロード先のディレクトリパスは、デフォルトで/var/lib/tftpboot
になっています。
今回はログ専用の保管先として、配下にディレクトリcisco_log
を作成しました。
[root@localhost /]# mkdir /var/lib/tftpboot/cisco_log
ゲストシェル(仮想Linux環境)のセットアップ
以前投稿した記事と同じ手順でセットアップしました。
[ネタ投稿]Cisco On-Box Pythonを使ってログインバナーをどうぶつの森風にしてみた
作成したログファイルはflash:
に保存されるようにします。ゲストシェルからは、ルートディレクトリ直下の/flash
として見えます。
cat9300-1#dir
Directory of flash:/
639009 -rw- 24197 May 11 2019 12:47:51 +00:00 cat9300-1_20190511.log
cat9300-1#guestshell
[guestshell@guestshell ~]$ pwd
/home/guestshell
[guestshell@guestshell ~]$ cd /
[guestshell@guestshell /]$ ls
bin data flash local opt sbin tmp
boot dev home lost+found proc selinux unfix_sshd.sh
bootflash etc lib media root srv usr
cisco fix_sshd.sh lib64 mnt run sys var
[guestshell@guestshell /]$ ls -l flash
lrwxrwxrwx 1 root root 10 Feb 15 2018 flash -> /bootflash
[guestshell@guestshell /]$ cd /flash
[guestshell@guestshell flash]$ ls -l cat9300-1_20190511.log
-rw-rw-r-- 1 65534 network-admin 24197 May 11 12:47 cat9300-1_20190511.log
Pythonスクリプトの作成
おおまかな手順は以下の通りです。
-
get_hostname
で、Configからホスト名を抽出。(ログファイル名で使用。) -
get_log
でshowコマンドを取得し、ローカルファイル保存。 -
file_transfer
でCatalyst9300からTFTPサーバへファイル転送。
※冒頭でfile prompt quiet
コマンドを実行していますが、これは後続のcopy
コマンド実行時、宛先IPアドレスやファイル名を聞かれないようにするためです。
※TFTPサーバ接続IFがVRFMgmt-vrf
に属しているため、copy
コマンドでvrf指定しています。
from cli import configure, cli
import datetime
# Set Global variables to be used in later functions
tftp_path = '10.10.20.20/cisco_log'
command_list = ['show clock', 'show version', 'show running-config', 'show environment all']
def get_hostname():
sh_run_host = cli('show run | include hostname')
host_strip = sh_run_host.strip()
hostname = host_strip.lstrip('hostname ')
print 'Hostname of this device is %s' % (hostname)
return hostname
def get_log(hostname, command_list):
filename = hostname + '_' + datetime.date.today().strftime('%Y%m%d') + '.log'
filepath = '/flash/' + filename
with open(filepath, 'w') as f:
for command in command_list:
f.write('\n-------- ' + command + ' --------\n')
output = cli(command)
f.write(output)
return filename
def file_transfer(tftp_path, file, file_system='flash:/'):
source = file_system + file
# Set commands to prepare for file transfer
tftp_commands = ['file prompt quiet', 'ip tftp blocksize 8192']
results = configure(tftp_commands)
print '*** Successfully configure "file prompt quiet" on switch ***'
transfer_file = "copy %s tftp://%s/%s vrf Mgmt-vrf" % (source, tftp_path, file)
print 'Transferring %s to %s' % (file, tftp_path)
transfer_results = cli(transfer_file)
if 'copied' in transfer_results:
print '*** %s was transferred successfully!!! ***' % (file)
elif 'Error opening' in transfer_results:
raise ValueError("XXX Failed Xfer XXX")
def main():
print '###### STARTING LOG TRANSFER SCRIPT ######'
print '\n*** Obtaining hostname of device.. ***'
hostname = get_hostname()
print '*** Getting logs.. ***'
filename = get_log(hostname, command_list)
print '*** Transferring log file to TFTP server.. ***'
file_transfer(tftp_path, filename)
print '###### FINISHED LOG TRANSFER SCRIPT ######'
if __name__ in "__main__":
main()
NW機器側のCLI設定
Pythonスクリプト実行のための条件をEEMで記述します。今回はSyslog発生をトリガーにしています。
具体的には、グローバルコンフィグレーションモードから特権モードに戻る時に発生する%SYS-5-CONFIG_I:~
を検知した場合に、log_transfer2.py
を実行するようにしています。
event manager applet LOG_TRANSFER
event syslog pattern "%SYS-5-CONFIG_I: Configured from"
action 1.0 cli command "enable"
action 2.0 cli command "guestshell run python /flash/log_transfer2.py --apply"
なお、EEM実行時、Pythonスクリプト内のprint
コマンドは標準出力されません。
出力結果を見ながら、スクリプト単体の動作確認をしたい場合は、以下コマンドを実行します。
cat9300-1#guestshell run python /flash/log_transfer2.py --apply
実行後の確認
適当に設定変更を行い、以下のshowコマンドで問題なく動作していること(Triggeredのカウントアップがみられること)を確認します。
cat9300-1#sh event manager statistics policy
Average Maximum
No. Class Triggered Suppressed Run Time Run Time Name
-------------------------------------------------------------------------------
1 applet 2 0 0.406 0.456 intShut
event {} syslog
2 applet 13 0 6.404 20.042 LOG_TRANSFER
event {} syslog
TFTPサーバ側で、ファイル転送されていることを確認します。
(python2) [root@localhost /]# cd /var/lib/tftpboot/cisco_log
(python2) [root@localhost cisco_log]# ls -l
total 24
-rw-rw-rw-. 1 root root 24197 May 11 14:38 cat9300-1_20190511.log
(python2) [root@localhost cisco_log]# cat cat9300-1_20190511.log
-------- show clock --------
*12:47:51.815 UTC Sat May 11 2019
-------- show version --------
Cisco IOS XE Software, Version 16.08.01a
Cisco IOS Software [Fuji], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 16.8.1a, RELEASE SOFTWARE (fc1)
~~省略~~
-------- show running-config --------
Building configuration...
Current configuration : 19512 bytes
!
! Last configuration change at 12:47:49 UTC Sat May 11 2019 by admin
!
version 16.8
~~省略~~
最後に
プログラミングの勉強と、日々もっと楽をしたい思いから作ってみました。
ただこのスクリプトだと、グローバルコンフィグレーションモードに入ったものの、設定変更しなかった場合もログ取得が走ってしまうので、もうちょっと考慮が必要かも知れません。