Perl访问华为系列交换机路由器配置参数模块

#包名: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访问华为系列交换机路由器配置参数模块)