ネットワーク機器のCLIって最強のAPIだと思うんですw
今使ってるネットワーク機器がRESTful API対応してなくても、NetConfに対応してなくても、ナウいSDKとかライブラリとかメーカさんから提供されていなくても、
CLIがあれば全然自動化できちゃいます!
今回は、PerlのNet::Telnetモジュールを用いて、L2スイッチの自動設定を試してみようと思います。
私のようにPerlしか書けない老害でも全然自動化できちゃいます!
Perl Net::Telnetモジュールとは?
Telnetを用いてネットワーク機器の対話型インターフェイス(CLI)を人間的に操作するのと同様、Perlスクリプトから機械的に同様の操作を実現することができます。
CPANのページが以下にあります。
http://search.cpan.org/~jrogers/Net-Telnet-3.04/lib/Net/Telnet.pm
Linux等でexpectコマンドを使って自動化されている方も多いと思いますが、それと似たような感覚です。Net::TelnetはTelnetに特化した機能を備えています。
Perl Net::Telnetモジュールのインストール
CentOS等であれば、コマンド一発で入ります。
$ yum install -y perl-Net-Telnet
インストール後、以下コマンドでマニュアルを表示できます。
$ perldoc Net::Telnet
例1. ネットワーク機器の設定を取得する
まず簡単な例として、ネットワーク機器に自動ログインしてrunning-configを取得してみます。ここでは試しにApresia15000を使ってます。
このスクリプトを1日1回とか実行してgitに登録すれば、設定の履歴管理ができちゃいますね!!
#!/usr/bin/env perl
use Net::Telnet;
$remote = shift || die;
$telnet = new Net::Telnet(
Timeout => 60,
Input_log => 'telnet.log',
);
$telnet->open($remote) or die;
$telnet->waitfor('/login: /');
$telnet->print('adpro');
$telnet->waitfor('/Password:/');
$telnet->print('password');
$telnet->waitfor('/> /');
$telnet->print('enable');
$telnet->waitfor('/# /');
$telnet->print('conf term');
$telnet->waitfor('/# /');
$telnet->print('terminal length 0');
$telnet->waitfor('/# /');
$telnet->print('end');
$telnet->waitfor('/# /');
$telnet->print('show running-config');
($out) = $telnet->waitfor('/# /');
print $out;
$telnet->print('exit');
exit;
Apresiaちゃんは、configureモードに移行しないとページャをオフにできないので、ちょっとややこしいですね(terminal length 0 の部分)。
このスクリプトを実行すると、標準出力に設定が表示されると思います。
$ ./ap15k-telnet.pl 192.168.9.82
show running-config
!
! Configuration for AEOS 8.19.03
! Date: Thu Mar 03 15:01:44 2016
! Hardware Model: Apresia15000-32XL-PSR
!
hostname TEST-AP15K-F16
!
username adpro adpro
username user user
<snip>
例2. インターフェイスのVLAN設定をクリアする
次に、複数ポートに対してVLANの設定を削除しシャットダウンするまでを自動化してみます。ある検証が終わって、設定をクリアするのに便利ですw
以下のような感じです。
#!/usr/bin/env perl
use Net::Telnet;
$remote = shift || die;
$telnet = new Net::Telnet(
Timeout => 60,
Input_log => 'telnet.log',
);
$telnet->open($remote) or die;
$telnet->waitfor('/login: /');
$telnet->print('adpro');
$telnet->waitfor('/Password:/');
$telnet->print('password');
$telnet->waitfor('/> /');
$telnet->print('enable');
$telnet->waitfor('/# /');
$telnet->print('conf term');
$telnet->waitfor('/# /');
foreach $port (5..8) {
$telnet->print("interface port 1/$port");
$telnet->waitfor('/# /');
$telnet->print("switchport mode trunk");
$telnet->waitfor('/# /');
$telnet->print("switchport trunk remove");
$telnet->waitfor('/# /');
$telnet->print("shutdown");
$telnet->waitfor('/# /');
}
$telnet->print('end');
$telnet->waitfor('/# /');
$telnet->print('write mem');
$telnet->waitfor('/# /');
$telnet->print('exit');
exit;
以下のように実行します。
$ ./ap15k-telnet.pl 192.168.9.82
別ターミナルでtailコマンドでログを追えば進捗がわかります。
$ tail -F telnet.log
Ethernet Switch Apresia15000-32XL-PSR
login: adpro
Password:
No entry for terminal type "network";
using dumb terminal settings.
No entry for terminal type "network";
using dumb terminal settings.
TEST-AP15K-F16> enable
TEST-AP15K-F16# conf term
Enter configuration commands, one per line. End with CNTL/Z.
TEST-AP15K-F16(config)# interface port 1/5
TEST-AP15K-F16(config-if-port)# switchport mode trunk
TEST-AP15K-F16(config-if-port)# switchport trunk remove
TEST-AP15K-F16(config-if-port)# shutdown
<snip>
TEST-AP15K-F16(config-if-port)# interface port 1/8
TEST-AP15K-F16(config-if-port)# switchport mode trunk
TEST-AP15K-F16(config-if-port)# switchport trunk remove
TEST-AP15K-F16(config-if-port)# shutdown
TEST-AP15K-F16(config-if-port)# end
TEST-AP15K-F16# write mem
Current running-config is saved to flash-config.
Writing to flash memory...
[OK]
Writing to SD memory...
ERROR: SD Memory card mount error
TEST-AP15K-F16#
とても便利ですね。ただし、**間違えて本番機に適用するとギャー!!**となりますのでご注意ください!!
注意事項:例示したコードはわかりやすさ優先のために、冗長だったりエラー処理がなかったりします。本番環境では、適宜追加してお使いください。