www.pudn.com > filecollector.rar > FC_Collector.pm
package FC_Collector;
###############################################################################
#
# @(#) Perl Module: FC_Collector
#
# Copyright(C) 2002-2004 BOCO Inter-Telecom DC Team, All Rights Reserved
#
# Author(s): JiaXiaoLong
#
# Creation Date: 2002/12/12
#
# Description:1.This package is the base of file collection.It reads the config
# file, connects bss or msc and sends commands to collect data.
# 2.The second functions of this module are: common prepare method
# and common postprocess method.
#
###############################################################################
use Env qw(NPM_HOME);
use XML::Simple;
use Data::Dumper;
use threads;
use threads::shared;
use StdCollect;
use StdConnect;
@ISA=("StdCollect","StdConnect");
use Exporter;
@ISA=('Exporter');
@EXPORT=qw(WriteHash2Col_cfg);
use lib "$NPM_HOME/common/modules";
use DBIs;
##############################################################
#
# Function:new
#
# Input:
#
# Output:
#
# Return value:
#
# Description:create filecollector
#
#
#############################################################
sub new{
my ($pkg,$Assistant_Var,$ErrMessage_hdl,$db_para) = @_;
my $filecollector=bless{
'Assistant_Var'=> $Assistant_Var,
'ErrMessage_hdl'=> $ErrMessage_hdl,
'db_para' => $db_para,
'connect_handle'=>'NULL',
'connect_func'=>'NULL',
'command_func'=>'NULL'
},$pkg;
return $filecollector;
}
#----------------------------------------------------------------------#
# common file collection part.
#----------------------------------------------------------------------#
##############################################################
#
# Function:creat_method_function
#
# Input:
#
# Output:
#
# Return value:connect and command functions
#
# Description: read method_module.xml
#
#
#############################################################
sub creat_method_function{
my $colcfg="$NPM_HOME/common/mbin/filecollector/config/method_func.xml";
DBIs::Trace("Read method_func file: $colcfg\n");
if(!(-r $colcfg)){
$err_msg="Can't read file $colcfg .\n File:".__FILE__."\t Line:".__LINE__."\n";
DBIs::Trace("$err_msg");
return (-1,$err_msg,'','');
}
$act_func_map=eval{XMLin("$colcfg")};
if($@){
$err_msg="$@ File:".__FILE__."\t Line:".__LINE__."\n";
return (-1,$err_msg,'','');
}
return (1,'success\n',$act_func_map->{'Connect_Method'},$act_func_map->{'Command_Method'});
}
##############################################################
#
# Function:connect_ne
#
# Input:1.connect information which has structure:
# {
# connect_type,
# other necessary information.
# }
# 2.connect handle
# Output:
#
# Return value:$return_code,$return_message,$connect_hdl.
# $return_code=1,success, others fail.
#
# Description:this function is designed to control all kinds of
# connection.
#
#
#############################################################
sub connect_ne{
my ($pkg,$connect_inf,$connect_hdl)=@_;
my ($result_code,$result_msg);
my $connect_type=lc($connect_inf->{'Connect_type'});
my $connect_func=$pkg->{'connect_func'}{$connect_type}{'Function'};
# print "$connect_type\n";
# print "$connect_func\n";
#----------------------------------
# handle NULL connection: rcp,rsh
#----------------------------------
if($connect_type=~/NULL/i){
return (1,"success \n",$connect_hdl);
}
if(!(defined $connect_func)){
return(-1," the type of $connect_type is not used \n",$connect_hdl);
}
else {
#print Dumper $connect_hdl;
DBIs::Trace("Connect Func:$connect_func\n");
($result_code,$result_msg,$connect_hdl)=$pkg->$connect_func($connect_inf,$connect_hdl);
if($result_code==1){
return (1,"$connect_type success\n",$connect_hdl);
}
else{
return (-1,$result_msg);
}
}
}
##############################################################
#
# Function:execute_connect
#
# Input: the ref hash of connection information.
#
# Output:
#
# Return value:1 connect succes, -1 connect fail
#
# Description:connect omc/oss/terminal and bss/msc,etc.
#
#
#############################################################
sub execute_connect{
my ($pkg,$cnt_inf)=@_;
my $max_retry=$cnt_inf->{'retry'}{'maxtimes'};
if (!$max_retry){$max_retry=0;}
#-------------------------------------------------
# $ne1_cntinf is omc/oss connection information
# and
# $ne2_cntinf is bss/msc connection information
#-------------------------------------------------
$cnt_inf= $pkg->Format_HashStruc($cnt_inf);
my $ne1_cntinf= $cnt_inf->{'ne'};
my $ne2_cntinf= $cnt_inf->{'ne'}{'child_ne'};
delete $ne1_cntinf->{'child_ne'};
my ($return_code,$return_msg,$err_msg,$connect_hdl);
my $retry_times=0;
while(($retry_times<=$max_retry)){
$retry_times++;
#----------------------------
# connect omc/oss
#----------------------------
($return_code,$return_msg,$connect_hdl)=$pkg->connect_ne($ne1_cntinf,0);
#---------------------------------------------------------
# connect omc/oss error, retry here.
#---------------------------------------------------------
if ($return_code==-1){
$err_msg=$return_msg."\n\tFile:".__FILE__."\n\tLine:".__LINE__."\n";
next;
}
#---------------------------------------------------------
# connect bss/msc. if connection is error here , we
# close the connect handle comming from connecting omc/oss
#---------------------------------------------------------
($return_code,$return_msg,$connect_hdl)=$pkg->connect_ne($ne2_cntinf,$connect_hdl);
#---------------------------------------------------------
# connect msc/bss error, retry here.
#---------------------------------------------------------
if ($return_code==-1){
$err_msg=$return_msg."\n\tFile:".__FILE__."\n\tLine:".__LINE__."\n";
next;
}
#---------------------------------------------------------
# success. Note, for rcp&rsh,connection doesn't need.
# $pkg->{'connect_handle'}= NULL is in this case.
#---------------------------------------------------------
if($connect_hdl){
$pkg->{'connect_handle'}=$connect_hdl;
}
return (1,"Connect successfully\n");
}
#--------------------------------
# fail,need trace here.
#--------------------------------
return (-1,$err_msg);
}
##############################################################
#
# Function:execute_cmdlist
#
# Input: command information
#
# Output: data file collected
#
# Return value:1 success -1 fail.
#
# Description:execute all command listed in collection config file.
#
#
#############################################################
sub execute_cmdlist{
my ($pkg,$cmd_inf,$err_inf)=@_;
my $r_cmd_list=$cmd_inf;
#----------------------------------------------
# if there is only one item in command list
# we have to change the hash stucture here.
#----------------------------------------------
if(exists $r_cmd_list->{'name'}){
delete $r_cmd_list->{'name'};
%cmd_list=("1"=>$r_cmd_list);
}
else{
if(exists $r_cmd_list->{'id'}){
%cmd_list=("1"=>$r_cmd_list);
}
else{
%cmd_list=%$r_cmd_list;
}
}
#----------------------
# add $share_hdl
#----------------------
my $share_hdl;
#modify by jzw 20041101
my @err_file,$err_count=0;
print "\n###### NORMAL GET FILE START ######\n";
foreach $cmd_index (sort{$a<=>$b} keys %cmd_list){
#print "\n######cmd_index is :$cmd_index######\n";
my $r_current_cmdinf=$cmd_list{$cmd_index};
$r_current_cmdinf->{'Ftp_state'} = 0;
my $error_tag = $r_current_cmdinf->{'Error_tag'};
my $flow_tag = $r_current_cmdinf->{'Flow_tag'};
DBIs::Trace("Current Step: $cmd_index");
my ($return_code,$return_msg,$share_handle)=$pkg->execute_current_cmd($r_current_cmdinf,$err_inf,$error_tag,$share_hdl);
$share_hdl=$share_handle;
DBIs::Trace("Step $cmd_index: $return_code");
#---------------------------------------------------
# serious error, we must interrupt current work flow
# and return back. need trace here.
#---------------------------------------------------
my $err_msg=$return_msg." File:".__FILE__."\t Line:".__LINE__."\n";
if (($return_code==1)){
next;
}
if (($return_code==-2)){
#modify by jzw 20041101 for error repeat get;
$err_count = $err_count + 1;
#print "\n###### remotefile is:$r_current_cmdinf->{'remotefile'} ###########\n";
@err_file[$err_count] = $cmd_list{$cmd_index};
#modify by wengzy for error skip
# next;
#$return_code=check_return_code($return_code,$err_inf,$return_msg);
#print "return_code=$return_code \n";
}
if (($return_code==-1)){
#modify by wengzy for error skip
next;
if ($flow_tag =~ /next/i) {
DBIs::Trace("\n\nWorkFlow is next ...\n");
next;
}
else {
#return (-1,$err_msg)
}
}
print "\n###### NORMAL GET FILE END ######\n";
#print "\n###### ERR FILE IS######\n";
#print Dumper(@err_file);
my $i;
if(@err_file>0){
print "\n###### GET ERRFILE AGAIN START######\n";
DBIs::Trace("Err File Get Repeat Start:");
for ($i=1;$i<=@err_file;$i++){
#print "\n###### AGAIN r_current_cmdinf is:$err_file[$i] ######\n";
my $r_current_cmdinf=$err_file[$i];
$r_current_cmdinf->{'Ftp_state'} = 1;
#print "\n######r_current_cmdinf is ######################\n";
#print Dumper($r_current_cmdinf);
my $error_tag = $r_current_cmdinf->{'Error_tag'};
my $flow_tag = $r_current_cmdinf->{'Flow_tag'};
DBIs::Trace("Current Step: $cmd_index");
my ($return_code,$return_msg,$share_handle)=$pkg->execute_current_cmd($r_current_cmdinf,$err_inf,$error_tag,$share_hdl);
$share_hdl=$share_handle;
DBIs::Trace("Step $cmd_index: $return_code");
my $err_msg=$return_msg." File:".__FILE__."\t Line:".__LINE__."\n";
if (($return_code==1)){
next;
}
if (($return_code==-2)){
next;
}
if (($return_code==-1)){
next;
if ($flow_tag =~ /next/i) {
DBIs::Trace("\n\nWorkFlow is next ...\n");
next;
}
else {
#return (-1,$err_msg)
}
}
}
DBIs::Trace("Err File Get Repeat End");
print "\n###### GET ERRFILE AGAIN END ######\n";
}
}
#--------------------------
# need trace here.
#--------------------------
return (1,"Finish execute command list.\n");
}
##############################################################
#
# Function:execute_current_cmd
#
# Input: current command which will be execute here.
#
# Output:
#
# Return value:1,success -1 error.
#
# Description:this function is called by sub execute_cmdlist.
#
#
#############################################################
sub execute_current_cmd{
my ($pkg,$r_current_cmdinf,$r_current_errinf,$error_tag,$share_hdl)=@_;
my $cmd_type=lc($r_current_cmdinf->{'cmd_type'});
my $cmd_func=$pkg->{'command_func'}{$cmd_type}{'Function'};
print "$cmd_type\n";
print "$cmd_func\n";
my ($return_code,$return_msg,$return_hdl);
if(!(defined $cmd_func)){
# print "the type of $cmd_type is not used\n";
return(-1," $cmd_type is not used \n");
}
else {
# print "Cmd is correct, Func: $cmd_func\n";
eval{
#print "\n##########r_current_cmdinf ##################\n";
#print Dumper($r_current_cmdinf);
($return_code,$return_msg,$return_hdl)=$pkg->$cmd_func($r_current_cmdinf,$r_current_errinf,$error_tag,$share_hdl);
};
#---------------------------------------------
# fail
# need trace here.
#---------------------------------------------
if($@){
return (-1,"$@"." File:".__FILE__."\n"." Line:".__LINE__."\n");
}
return ($return_code,$return_msg,$return_hdl);
}
}
##############################################################
#
# Function:read_colcfg
#
# Input:collection config file($colcfg)
#
# Output:
#
# Return value:1.return_code:1 success, -1 fail
# 2.return_msg: success or error message.
# 3.connection information
# 4.command information
# Description: get connection and command information from collection
# config file.
#
#
#############################################################
sub read_colcfg{
my ($pkg,$colcfg)=@_;
my ($col_inf,$cnt_inf,$cmd_inf,$err_inf,$err_msg);
if(!(-r $colcfg)){
$err_msg="Can't read file $colcfg .\n File:".__FILE__."\t Line:".__LINE__."\n";
return (-1,$err_msg,'','');
}
$col_inf=eval{XMLin("$colcfg")};
if($@){
$err_msg="$@ File:".__FILE__."\t Line:".__LINE__."\n";
return (-1,$err_msg,'','');
}
$cnt_inf=$col_inf->{'Connect_Region'};
$cmd_inf=$col_inf->{'Command_Region'};
$err_inf=$col_inf->{'Error_Region'};
# print "Connect Region is:\n",Dumper($cnt_inf),"\n";
# print "Command Region is:\n",Dumper($cmd_inf),"\n";
return (1,"Read $colcfg success.\n" ,$cnt_inf,$cmd_inf,$err_inf);
}
##############################################################
#
# Function:collect_data
#
# Input:collection config file
#
# Output:data file collected.
#
# Return value:1 success, -1 fail.
#
# Description: called by sub FC_TaskProcessor::execute_workflow.
# control each step of collection.
#
#
#############################################################
sub collect_data{
my ($pkg,$colcfg)=@_;
DBIs::Trace("Begin collecting data...\n");
DBIs::Trace("Collector Config_file is: $colcfg\n");
#-------------------------------------------
# read collection config file,get connection
# information and command information
#-------------------------------------------
my($returncode,$return_Msg);
($returncode,$return_msg,$pkg->{'connect_func'},$pkg->{'command_func'})=creat_method_function();
if ($return_code == -1) {
DBIs::Trace("Can't Read Work Method! \n");
return -1;
}
#---------------------------------------------
# Read Col_cfg , Split it to 3 parts
#---------------------------------------------
my ($return_code,$return_msg,$cnt_inf,$cmd_inf,$err_inf)=$pkg->read_colcfg($colcfg);
DBIs::Trace("$return_msg");
if ($return_code == -1) {
return $pkg->move_colcfg(-1,$colcfg);
}
DBIs::Trace("Finished read col_cfg\n");
#-------------------------------------------
# connect net element
#-------------------------------------------
($return_code,$return_msg)=$pkg->execute_connect($cnt_inf);
DBIs::Trace("$return_msg");
if ($return_code == -1) {
return $pkg->move_colcfg(-1,$colcfg);
}
DBIs::Trace("finished connect\n");
#-------------------------------------------
#send command and collect data
#-------------------------------------------
($return_code,$return_msg)=$pkg->execute_cmdlist($cmd_inf,$err_inf);
DBIs::Trace("$return_msg");
if ($return_code==-1) {
return $pkg->move_colcfg(-1,$colcfg);
}
#-------------------------------------------
# success.
#-------------------------------------------
DBIs::Trace("finish data collection.\n");
return $pkg->move_colcfg(1,$colcfg);
}
##############################################################
#
# Function:move_colcfg
#
# Input:return_code,collection config file
#
# Output:
#
# Return value:return_code
#
# Description: called by sub collect_data.
# move collection config file($colcfg) to
# different path according to return_code.
#
#
#############################################################
sub move_colcfg{
my ($pkg,$return_code,$colcfg)=@_;
#----------------------------------------
# get colcfg's upper path.
#----------------------------------------
$colcfg=~/(.*)\/new/;
my $upper_path=$1;
if($return_code==1){
DBIs::Trace("mv $colcfg $upper_path/success/ \n");
if(!(-d "$upper_path/success/")) {
system("mkdir $upper_path/success/");
}
system ("mv $colcfg $upper_path/success/");}
if($return_code==-1){
DBIs::Trace("mv $colcfg $upper_path/fail/ \n");
if(!(-d "$upper_path/fail/")) {
system("mkdir $upper_path/fail/");
}
system ("mv $colcfg $upper_path/fail/");}
return $return_code;
}
##############################################################
#
# Function:check_return_code
#
# Input:$err_inf
#
# Output:
#
# Return value:
#
# Description:
#
#
#############################################################
sub check_return_code{
my $return_code=shift;
my $err_full_inf=shift;
my $err_msg=shift;
$err_inf=$err_full_inf->{'error'};
foreach $err_value(values %$err_inf){;
if ($err_msg=~/$err_value->{'error_des'}/){;
if ($err_value->{'action'} eq "halt"){
return -1;
}
return 1;
}
}
if ($err_full_inf->{'default'} eq "next")
{ return 1;}
return -1;
}
##############################################################
#
# Function: WriteHash2Col_cfg
#
# Input:
#
# Output:
#
# Return value:
#
# Description: Write Col_config file for Collect
#
##############################################################
sub WriteHash2Col_cfg {
my ($template_inf,$outputfilename,$task_id) = @_;
#---------------------------------------
# Deal With Command Region
#---------------------------------------
my $command = $template_inf->{'Command_Region'}{'cmd'};
delete $template_inf->{'Command_Region'}{'cmd'};
if (exists $command->{'id'}) {
delete $command->{'id'};
$command = {"1"=>$command};
} elsif (exists $command->{'name'}) {
delete $command->{'name'};
$command = {"1"=>$command};
}
my $Command_Region = "\n";
foreach my $id (keys %$command) {
my $cmd_line ="\t{$id};
foreach my $value (keys %$cmd) {
$cmd_line .= "$value=\"".$cmd->{$value}."\" ";
}
chop($cmd_line);
$cmd_line .= "/>\n";
$Command_Region .= $cmd_line;
}
$Command_Region .= " \n";
#--------------------------------------
# Deal with Connect & Error Region
#--------------------------------------
my $tmpfile ="/tmp/$task_id"."_tmpfile";
eval{XMLout($template_inf,outputfile=>"$tmpfile",rootname=>"")};
if ($@) {
print $@."File ".__FILE__."Line ".__LINE__."\n";
exit;
}
open (READ,$tmpfile) || die "Can't open file: $tmpfile\n";
my $Other_Region;
while () {
$Other_Region .= $_;
}
#--------------------------------------
# Write OutPutConfigFile
#--------------------------------------
open (WRITE,">$outputfilename") || die "Can't open file: $outputfilename
\n";
print WRITE "\n";
print WRITE $Command_Region;
print WRITE $Other_Region;
print WRITE " ";
close (WRITE);
return ($outputfilename);
}
##############################################################
#
# Function: Format_HashStruc
#
# Input:
#
# Output:
#
# Return value:
#
# Description:
#
#############################################################
sub Format_HashStruc {
my ($pkg,$hash_ref) = @_;
my $hash;
if(exists $hash_ref->{'id'}){
my $key = $hash_ref->{'id'};
$hash={"$key"=>$hash_ref};
delete $hash_ref->{'id'};
}
else{
if(exists $hash_ref->{'name'}){
my $key = $hash_ref->{'name'};
$hash={"$key"=>$hash_ref};
delete $hash_ref->{'name'};
}
else{
#-----------------------------------------------
# there are more than one steps in the work flow.
#-----------------------------------------------
$hash=$hash_ref;
}
}
return ($hash);
}
##############################################################
#
# Function: Data_filters
#
# Input: (\@remote_file,\@local_file,$task_id,$db_para)
# $db_para is a hash ref and it has following structure:
# {
# 'db_name'=> database name,
# 'server_name'=> db server name,
# 'db_user'=> user name,
# 'db_pwd' => user password
# }
#
# Output: (\@remote_file,\@local_file)
#
# Return value:
#
# Description: this fuction is used by 2 work type: MMI and FTP
# in FTP case , $remote_file and $local_file must be defined.
# in MMI case , the $local_file is null , and $remote_file is vendor_cmd.
#
###############################################################
sub Data_filters {
my ($pkg,$remote_file,$local_file,$task_id,$db_para) = @_;
my ($r,$str);
my $db_name = $db_para->{'db_name'};
my $db_server = $db_para->{'server_name'};
my $db_usr = $db_para->{'db_user'};
my $db_passwd = $db_para->{'db_pwd'};
my $connect_str = "dbi:Informix:$db_name"."\@$db_server";
my $db_hdl = DBI->connect($connect_str, $db_usr, $db_passwd);
my $lock_mode = "set lock mode to wait 60";
$db_hdl->do($lock_mode);
my $sql = "select distinct vendor_data from dal_log where vendor_data= ? and task_id= ? and program_name=\"filecollector\"";
my $sth =$db_hdl->prepare($sql)|| (($r=$DBI::err)&&($str=$DBI::errstr));
if ($r) {
$db_hdl->rollback;
print " $r \n$str";
exit(-1);
}
my (@remote_tmp,@local_tmp,@new_remotefile,@new_localfile);
@remote_tmp = @$remote_file;
if ($local_file) {
@local_tmp = @$local_file;
}
for (my $i=0;$i<@remote_tmp;$i++) {
my $datafile = $remote_tmp[$i];
$sth->bind_param(1,$datafile);
$sth->bind_param(2,$task_id);
$sth->execute || (($r=$DBI::err) &&($str=$DBI::errstr));
my @row_ary = $sth->fetchrow_array;
if ($row_ary[0]) {
push @new_remotefile, $datafile;
if ($local_file) {
push @new_localfile, $local_tmp[$i];
}
}
}
$db_hdl->disconnect();
if ($local_file) {
return (\@new_remotefile,\@new_localfile);
}else {
return (\@new_remotefile);
}
}
#######################################################################
#
# Function: write_dallog
#
# Input:
#
# Output:
#
# Description:
#
#
#######################################################################
sub write_dallog {
my ($pkg,$error_message,$col_tag,$message_class) = @_;
my $v2c_map = $pkg->{'Assistant_Var'}{'v2c_map'};
my $error_hdl = $pkg->{'ErrMessage_hdl'};
my $db_para = $pkg->{'db_para'};
my $common_tmp = $error_hdl->{'common'};
my ($v2c_tmp,$dallog_msg);
foreach my $id (keys %$v2c_map) {
my $vendor_data = $v2c_map->{$id}{'vendor_data'};
if ($col_tag =~ /$vendor_data/i) {
$v2c_tmp = $v2c_map->{$id};
}
}
foreach my $key (keys %$common_tmp) {
$dallog_msg->{$key} = $common_tmp->{$key};
if (!($dallog_msg->{$key})) {
$dallog_msg->{$key} = '';
}
}
foreach my $key (keys %$v2c_tmp) {
$dallog_msg->{$key} = $v2c_tmp->{$key};
if (!($dallog_msg->{$key})) {
$dallog_msg->{$key} = '';
}
}
$dallog_msg->{'error_message'} = $error_message;
$dallog_msg->{'message_class'} = $message_class;
my $db_dbname= $db_para->{'db_name'};
my $db_server= $db_para->{'server_name'};
my $db_pwd= $db_para->{'db_pwd'};
my $db_user= $db_para->{'db_user'};
my ($return_code,$return_msg) =$error_hdl->connect_DB($db_type,$db_server,$db_dbname,$db_user,$db_pwd);
if ($return_code < 0) {
DBIs::Trace("Can't Connect to DB Write Dal_log !!\n$return_msg");
return $return_code;
}
($return_code,$return_msg) = $error_hdl->WritelogTbl($dallog_msg);
if ($return_code < 0) {
DBIs::Trace("Can't Write Dal_log !!\n$return_msg");
return $return_code;
}
my $db_hdl = $error_hdl->{'db_handle'};
$db_hdl->disconnect();
undef($db_hdl);
delete $error_hdl->{'db_handle'};
return(1);
}
1;