#包名:HWNET 功能:对华为交换机和路由器进行自动维护的包 引用方法:use HWNET;
#
package HWNET;
use strict;
use Data::Dump qw(dump);
use Net::Telnet;
use POSIX qw(strftime);
use Net::Ping;
#
# 用于测试的子程序
#
sub test{
#读取子程序参数
my $this = shift;
my $telnet = $this->{'TELNET_OBJECT'};
my $prompt = $this->{'PROMPT'};
$telnet->put("\n");
#my ($prematch, $match) = $telnet->waitfor("/$prompt/");
print $telnet->lastline;
return ;
}
#
# 功能:支持的设备型号列表
#
# 列表项示例:
# S8016' => 'Quidway S8016 Routing Switch'
# ^
# 设备型号 'disp ver'命令输出结果中标志设备型号的特征字符串
#
# 说明: 如果需要支持新的设备型号支持,需要在此列表中增加相应的条目
#
my %device_type_list =(
'S8016' => 'Quidway S8016 Routing Switch',
'NE05' => 'Quidway NetEngine 05',
'NE40-8' => 'Quidway NetEngine 40-8 Universal Switching Router',
'NE16' => 'Quidway NetEngine 16E',
'AR46-40' => 'Quidway AR46-40',
'S3050' => 'Quidway S3050C',
'S2026' => 'Quidway S2026',
'S2403H-EI' => 'Quidway S2403H-EI',
'S3526E' => 'Quidway S3526E',
'S2008-EI' => 'Quidway S2008-EI',
'S3050C' => 'Quidway S3050C',
);
# 返回程序包支持的设备型号列表
sub supported_device_type_list{
return keys %device_type_list;
}
#
# HWNET对象的构造器
#
sub new{
my $class = shift;
my $this = {
'STATE'=>'UNCONNECTED',
'INPUT_LOG'=>'in.txt',
'OUTPUT_LOG'=>'out.txt',
'TIMEOUT'=>5, 'PROMPT'=>''
};
return bless $this, $class;
}
#
#登录到网络设备的用户视图
#
sub reset{
my $this = shift;
# 关闭telnet对象
my $telnet = $this->{'TELNET_OBJECT'};
$telnet->close() if $telnet;
# 将各对象各属性复位到初始值
$this = {
'STATE' => 'UNCONNECTED',
'INPUT_LOG' => 'input_log.txt',
'OUTPUT_LOG' => 'output_log.txt',
'TIMEOUT' => 5,
'PROMPT' => ''
};
}
sub login{
#读取子程序参数
my ($this, $host,$username, $password,$su_password) = @_;
my $prompt = $this->{'PROMPT'};
$prompt = '(?:<.+?>|\[.+?\])$' if !$prompt;
my $ret=undef; #设置子程序默认返回值
# 验证子程序执行的前提条件
return $ret if $this->{'STATE'} ne 'UNCONNECTED';
my $input_log = $this->{'INPUT_LOG'};
my $output_log = $this->{'OUTPUT_LOG'};
my $timeout = $this->{'TIMEOUT'};
my $telnet = Net::Telnet->new(
Timeout=>$timeout,
Prompt=>"/$prompt/",
Input_log=>$input_log,
Output_log=>$output_log,
Errmode=>'return'
);
#如果建立telnet对象失败,返回
return $ret unless $telnet;
$this->{'STATE'}='CONNECTED'; #设置HWNET对象状态
#登录到普通用户模式
return $ret unless $telnet->open($host);
my (undef, $match) = $telnet->waitfor('/Password:|Username:/');
if($match eq 'Username:'){
return $ret unless $telnet->put($username."\n");
return $ret unless $telnet->waitfor("/Password:/");
}
return $ret unless $telnet->put($password."\n");
return $ret unless $telnet->waitfor("/$prompt/");
$this->{'STATE'} = 'USERMODE';
#保存登录参数给后续操作使用
$this->{'TELNET_OBJECT'} = $telnet;
$this->{'USERNAME'} = $username;
$this->{'PASSWORD'} = $password;
$this->{'SU_PASSWORD'} = $su_password;
$this->{'PROMPT'} = $prompt;
$ret = 1;
return $ret;
}
#
#退出登录
#
sub logout{
my $this = shift;
my $state = $this->{'STATE'};
my $telnet =
$this->{'TELNET_OBJECT'};
my $prompt = $this->{'PROMPT'};
# 根据TELNET_OBJECT对象所处的不同状态进行不同的操作
$_ = $state;
SWITCH: { /^UNCONNECTED$/ && do {
last SWITCH;
};
/^CONNECTED$/ && do {
last SWITCH;
};
/^USERMODE$/ && do {
$telnet->put("quit\n"); $telnet->waitfor("/$prompt/");
last SWITCH;
};
/^SUPERMODE$/ && do {
$this->super; $telnet->put("quit\n");
$telnet->waitfor("/$prompt/"); last SWITCH;
};
}
$this->{'STATE'} = 'UNCONNECTED'; $telnet->close if $telnet; $telnet =
undef;
return 1;
}
#
#进入super模式
#
sub super{
#读取子程序参数
my $this = shift;
my $telnet = $this->{'TELNET_OBJECT'}; return undef unless $telnet;
my $su_password = $this->{'SU_PASSWORD'};
my $prompt = $this->{'PROMPT'};
my $state = $this->{'STATE'};
my $ret = undef;
my $myret = undef;
if($state eq 'USERMODE'){
#进入超级用户模式
$myret = $telnet->put("super\n");
goto out unless $myret;
my (undef, $match) = $telnet->waitfor("/ Password:|$prompt/i");
goto out if !defined($match);
if($match =~ /Password:/){
goto out unless $telnet->put($su_password."\n");
goto out unless $telnet->waitfor("/$prompt/");
}
$this->{'STATE'} = 'SUPERMODE'; my $ret = 1;
}
out: return $ret;
}
#
#获取设备sysname
#
sub get_sysname{
#读取子程序参数
my $this = shift; my $ret = undef; my $in="";
my $telnet = $this->{'TELNET_OBJECT'}; my $prompt = $this->{'PROMPT'}; my
$state = $this->{'STATE'};
#进入super模式
$this->super;
# TODO: 此处需要进行错误处理
#读取设备版本信息
$telnet->put("disp current-config\n");
#处理disp current-config的多页显示情况
my ($prematch, $match); do{{
($prematch, $match) = $telnet->waitfor("/--- More ---|$prompt/"); $in .=
$prematch; if($match =~ /--- More ---/){
$telnet->put(" ");
}
}}while $match =~ /--- More ---/;
$in =~ /sysname (.+)\n/;
$ret = $1; return $ret;
}
#
#获取设备型号
#
sub get_device_type{
#读取子程序参数
my $this = shift; my $ret = undef; my $in="";
my $telnet = $this->{'TELNET_OBJECT'}; my $su_password =
$this->{'SU_PASSWORD'}; my $prompt = $this->{'PROMPT'}; my $state =
$this->{'STATE'};
$this->super;
#读取设备版本信息
$telnet->put("disp version\n");
#处理disp ver的多页显示情况
my ($prematch, $match); do{{
($prematch, $match) = $telnet->waitfor("/--- More ---|$prompt/"); $in .=
$prematch; if($match =~ /--- More ---/){
$telnet->put(" ");
}
}}while $match =~ /--- More ---/;
#根据设备特征串匹配设备类型
study $in; for(keys %device_type_list){
$ret = $_, last if $in =~ /$device_type_list{$_}/;
}
return $ret;
}
#
# TODO: 增加对于错误处理的可靠性
#
sub backup_config{
#读取参数
my $this = shift;
#读取ftp服务器的参数
my ($ftp_server, $ftp_user, $ftp_password) = @_; my $p =
Net::Ping->new('tcp', 5);
return 0 if ! $p->ping($ftp_server); # 如果ftp服务器无法ping通则返回
#设置telnet参数
my $telnet = $this->{'TELNET_OBJECT'}; my $su_password =
$this->{'SU_PASSWORD'}; my $prompt = $this->{'PROMPT'};
# 判断系统的类型
my $sys_name = $this->get_sysname; my $sys_type = $this->get_device_type;
print STDERR $sys_type, "\n";
#根据系统类型的不同执行不同的配置备份过程
$_ = $sys_type; SWITCH: {
// && do { # 统一的过程
#0. 进入特权用户模式
$this->super;
#1. 确定配置文件名(要根据不同的设备型号来确定)
my ($pre, $match, $ret); my $config_name = 'config.cfg';
CONFIG_TYPE:{
/^NE05$/ && do{
$telnet->put("disp startup\n"); my
($prematch,undef) =
$telnet->waitfor("/$prompt/");
$prematch =~ /Next startup saved-configuration file:\s+(.+)$/m;
$telnet->buffer_empty;
$config_name = $1; last CONFIG_TYPE;
};
/^S8016$/ && do{
$config_name = 'vrpcfg.zip'; last CONFIG_TYPE;
}; /^NE40-8$/ && do{
#$telnet->put("disp startup\n"); my
#($prematch,undef) =
#$telnet->waitfor("/$prompt/"); $prematch =~
#/Next startup saved-configuration
#file:\s+(.+)$/m;
$telnet->buffer_empty;
$config_name = 'vrpcfg.zip';
last CONFIG_TYPE;
}; /^NE16$/ && do{
$telnet->put("disp startup\n"); my
($prematch,undef) =
$telnet->waitfor("/$prompt/"); $prematch =~ /Next startup saved-configuration file:\s+(.+)$/m;
$telnet->buffer_empty;
$config_name = $1; last CONFIG_TYPE;
}; /^AR46-40$/ && do{
$telnet->put("disp startup\n");
my ($prematch,undef) = $telnet->waitfor("/$prompt/");
$prematch =~ /Next startup saved-configuration file:\s+(.+)$/m;
$telnet->buffer_empty;
$config_name = $1;
last CONFIG_TYPE;
}; /^S3050$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
};
/^S3050C$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
};
/^S3526E$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
};
/^S2026$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
}; /^S2403H-EI$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
}; /^S2008-EI$/ && do{
$config_name = 'vrpcfg.txt';
last CONFIG_TYPE;
};
}
# 检查配置文件名
return 0 if $config_name eq '';
#2. 登录ftp服务器
# 延迟
sleep 2;
#
$telnet->put("ftp $ftp_server\n");
($pre, $match) = $telnet->waitfor('/User\(.*\)/');
return 0 if !$match or $match !~ /User\(.*\)/;
$telnet->put("$ftp_user\n");
$telnet->waitfor('/Password:$/');
$telnet->put("$ftp_password\n");
$telnet->waitfor('/\[ftp\]$/');
#3. 设置为二进制方式
$telnet->put("bin\n"); $telnet->waitfor('/\[ftp\]$/');
#4. 创建存放配置文件的目录
$telnet->put("mkdir netconfig\n");
$telnet->waitfor('/\[ftp\]$/');
#5. 进入目录
$telnet->put("cd netconfig\n");
$telnet->waitfor('/\[ftp\]$/');
#6. 生成备份目录名
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time);
$year += 1900; $mon += 1;
my $dir_name = "$year-$mon-${mday}_$sys_name";
$telnet->put("mkdir $dir_name\n");
$telnet->waitfor('/\[ftp\]$/');
#7. 进入备份目录
$telnet->put("cd $dir_name\n");
$telnet->waitfor('/\[ftp\]$/');
#8. 上传备份文件
$telnet->put("put $config_name\n"); ($pre, undef) =
$telnet->waitfor('/\[ftp\]$/');
return 0 if $pre !~ /200 PORT Command successful\./;
#退出ftp
$telnet->put("quit\n"); $telnet->waitfor("/$prompt/");
last SWITCH;
};
# /^$/ && do {
# last SWITCH;
# };
} return 1;
}
#
# 功能:将当前登录的vty终端设置为不暂停状态
#
sub set_vty_no_pause{
#读取子程序参数
my $this = shift; my $ret = undef; my $in="";
my $telnet = $this->{'TELNET_OBJECT'}; my $prompt = $this->{'PROMPT'}; my
$state = $this->{'STATE'};
my $tmp_type = $this->get_device_type;
$this->super;
#获取当前用户的虚拟终端号
$telnet->put("disp users\n");
#处理disp users的多页显示情况
my ($prematch, $match); do{{
($prematch, $match) = $telnet->waitfor("/--- More ---|$prompt/"); $in .=
$prematch; if($match =~ /--- More ---/){
$telnet->put(" ");
}
}}while $match =~ /--- More ---/;
$_ = $tmp_type; SWITCH: {
do {
# 生成命令行
$in =~ /[\+|\*]\s+\d+\s+VTY\s+(\d+)\s+\d\d:\d\d:\d\d\s/; my $ui =
$1; my $cmd = "user-interface vty $ui";
if(! $this->sys){
$telnet->put("system\n"); $telnet->waitfor("/$prompt/");
}
$telnet->put("$cmd\n"); $telnet->waitfor("/$prompt/");
$telnet->put("screen-length 0\n"); $telnet->waitfor("/$prompt/");
$telnet->put("quit\n"); $telnet->waitfor("/$prompt/");
$telnet->put("return\n"); $telnet->waitfor("/$prompt/");
last SWITCH;
}
}
$ret = 1; return $ret;
}
#
# 功能:将当前登录的vty终端设置为可暂停状态
#
sub set_vty_pause{
#读取子程序参数
my $this = shift; my $ret = undef; my $in="";
my $telnet = $this->{'TELNET_OBJECT'}; my $prompt = $this->{'PROMPT'}; my
$state = $this->{'STATE'};
my $tmp_type = $this->get_device_type;
$this->super;
#获取当前用户的虚拟终端号
$telnet->put("disp users\n");
#处理disp users的多页显示情况
my ($prematch, $match); do{{
($prematch, $match) = $telnet->waitfor("/--- More ---|$prompt/"); $in .=
$prematch; if($match =~ /--- More ---/){
$telnet->put(" ");
}
}}while $match =~ /--- More ---/;
$_ = $tmp_type;
SWITCH: {
do {
# 生成命令行
$in =~ /[\+|\*]\s+\d+\s+VTY\s+(\d+)\s+\d\d:\d\d:\d\d\s/; my $ui =
$1; my $cmd = "user-interface vty $ui";
if(! $this->sys){
$telnet->put("system\n"); $telnet->waitfor("/$prompt/");
}
$telnet->put("$cmd\n"); $telnet->waitfor("/$prompt/");
$telnet->put("undo screen-length\n"); $telnet->waitfor("/$prompt/");
$telnet->put("quit\n"); $telnet->waitfor("/$prompt/");
$telnet->put("return\n"); $telnet->waitfor("/$prompt/");
last SWITCH;
}
}
$ret = 1; return $ret;
}
#
# 功能:判断系统是否处理在system-view视图,是则返回1,否则返回0。
#
sub sys{
#读取子程序参数
my $this = shift;
my $telnet = $this->{'TELNET_OBJECT'}; my $prompt = $this->{'PROMPT'};
$telnet->put("\n"); my ($prematch, $match) = $telnet->waitfor("/$prompt/");
return 1 if $match =~ /\]$/; return 0 if $match =~ />$/; return 0;
}
sub send_ctrl_k{
my $this = shift;
my $telnet = $this->{'TELNET_OBJECT'}; my $prompt = $this->{'PROMPT'};
$telnet->put("\cK"); my ($prematch, $match) = $telnet->waitfor("/$prompt/");
return 1;
}
sub change_password{
}
#
#执行指定的命令
#
sub exec_cmd{
my $this = shift;
my $cmd = shift;
my $telnet = $this->{'TELNET_OBJECT'};
$telnet->cmd($cmd);
} 1;
Perl访问华为系列交换机路由器配置参数模块
最新推荐文章于 2024-07-12 08:26:22 发布