mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-31 03:12:30 +00:00 
			
		
		
		
	Restructure osdeplay code logic
This commit is contained in:
		
							
								
								
									
										684
									
								
								xCAT-probe/lib/perl/LogParse.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										684
									
								
								xCAT-probe/lib/perl/LogParse.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,684 @@ | ||||
| package LogParse; | ||||
|  | ||||
| # IBM(c) 2016 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
|  | ||||
| BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr'; } | ||||
| use lib "$::XCATROOT/probe/lib/perl"; | ||||
| use probe_global_constant; | ||||
| use probe_utils; | ||||
|  | ||||
| use strict; | ||||
| use Data::Dumper; | ||||
| use File::Path; | ||||
| use File::Copy; | ||||
| use Time::Local; | ||||
| use File::Basename; | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         The constructor of class 'LogParse' | ||||
|     Arguments: | ||||
|         Public attributes: | ||||
|             $self->{verbose}:scalar, Offer verbose information, used for handling feature logic | ||||
|         private attributes: | ||||
|             $self->{log_open_info}: reference of a hash, used to save the log file operating information.  | ||||
|             $self->{current_ref_year}: scalar, the year information of current time. such as 2016. Used for log time parsing | ||||
|             $self->{current_ref_time}:  scalar, the epoch format of current time, such as 1472437250. Used for log time parsing | ||||
|  | ||||
|             $self->{debug}: Scalar, offer debug information, used for hanlde code logic, used by developer to debug function running  | ||||
|             $self->{debuglogpath}: Scalar, the path of debug log files | ||||
|             $self->{debuglogfd}: File descriptor of debug log files | ||||
|  | ||||
|             The structure of "log_open_info" hash is: | ||||
|             $self->{log_open_info}->{<logfileshortname>}{openfd}  : The file descriptor of sepecific openning log file        | ||||
|             $self->{log_open_info}->{<logfileshortname>}{rotate_file_list} : Array, all rotate file about related log file | ||||
|             $self->{log_open_info}->{<logfileshortname>}{openning_file_index} : scalar, the index of openning file in rotate_file_list  | ||||
|             $self->{log_open_info}->{<logfileshortname>}{next_read_point} : scalar, the read point of one log file, used by 'seek' function | ||||
|             $self->{log_open_info}->{<logfileshortname>}{filetype} : scalar, the type of current log file, $::LOGTYPE_RSYSLOG or $::LOGTYPE_HTTP  | ||||
|             $self->{log_open_info}->{<logfileshortname>}{next_start_time} : scalar, the next read time | ||||
|  | ||||
|     Returns: | ||||
|        The instance of class | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub new { | ||||
|     my @args  = @_; | ||||
|     my $self  = {}; | ||||
|     my $class = shift; | ||||
|     $self->{verbose} = shift; | ||||
|  | ||||
|     my %log_open_info; | ||||
|     $self->{log_open_info} = \%log_open_info; | ||||
|  | ||||
|     my ($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime(time()); | ||||
|     $self->{current_ref_year} = $year; | ||||
|     $self->{current_ref_time} = time(); | ||||
|  | ||||
|     $self->{debug} = 0; | ||||
|     if ($self->{debug}) { | ||||
|         my $logfiledir = "/tmp/xcatprobedebug/"; | ||||
|         mkpath("$logfiledir") unless (-d "$logfiledir"); | ||||
|         $self->{debuglogpath} = $logfiledir; | ||||
|         $self->{debuglogfd}; | ||||
|     } | ||||
|  | ||||
|     bless($self, ref($class) || $class); | ||||
|     return $self; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Public functuon. Calculate the possible host name of current server in rsyslog files. | ||||
|     Arguments: | ||||
|         NULL | ||||
|     Returns: | ||||
|         A array which contains the possible host names of current server | ||||
|         Such as ("xxxxxx", "xxxxx.domain",....) | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_candidate_mn_hostname_in_log { | ||||
|     my $self = shift; | ||||
|  | ||||
|     my $svr_hostname_short = `hostname -s`; | ||||
|     chomp($svr_hostname_short); | ||||
|     my $svr_hostname_domain = `hostname -d`; | ||||
|     chomp($svr_hostname_domain); | ||||
|  | ||||
|     my @candidate_svr_hostname_inlog; | ||||
|     push(@candidate_svr_hostname_inlog, $svr_hostname_short); | ||||
|     push(@candidate_svr_hostname_inlog, "$svr_hostname_short.$svr_hostname_domain"); | ||||
|     if ($self->{debug}) { | ||||
|         my $tmpstr = ""; | ||||
|         $tmpstr .= "$_ " foreach (@candidate_svr_hostname_inlog); | ||||
|         probe_utils->send_msg("stdout", "d", "The candidate MN hostname in log are $tmpstr"); | ||||
|     } | ||||
|     return @candidate_svr_hostname_inlog; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Public function. Specify the log files scope which will be scaned. | ||||
|     Arguments: | ||||
|         NULL | ||||
|     Returns: | ||||
|         A hash which save all candidate log file information | ||||
|         $candidate_log{<label>}{file} | ||||
|         $candidate_log{<label>}{type} | ||||
|         <label> : The short name of log file  | ||||
|         file:  The log file name, including full path | ||||
|         type: The valid type are $::LOGTYPE_HTTP and $::LOGTYPE_RSYSLOG, refer to 'probe_global_constant' for more information. | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_log_file_list { | ||||
|     my $self = shift; | ||||
|     my %candidate_log; | ||||
|  | ||||
|     my @candidate_log_set; | ||||
|     push @candidate_log_set, "/var/log/messages" if (-e "/var/log/messages"); | ||||
|     push @candidate_log_set, "/var/log/xcat/cluster.log" if (-e "/var/log/xcat/cluster.log"); | ||||
|     push @candidate_log_set, "/var/log/xcat/computes.log" if (-e "/var/log/xcat/computes.log"); | ||||
|  | ||||
|     my $filename; | ||||
|     foreach my $log (@candidate_log_set) { | ||||
|         $filename = basename($log); | ||||
|         $filename =~ s/(\w+)\.(\w+)/$1/g; | ||||
|         $candidate_log{$filename}{file} = $log; | ||||
|         $candidate_log{$filename}{type} = $::LOGTYPE_RSYSLOG; | ||||
|     } | ||||
|  | ||||
|     my $httplog; | ||||
|     if (-e "/var/log/httpd/access_log") { | ||||
|         $httplog = "/var/log/httpd/access_log"; | ||||
|     } elsif (-e "/var/log/apache2/access_log") { | ||||
|         $httplog = "/var/log/apache2/access_log"; | ||||
|     } elsif (-e "/var/log/apache2/access.log") { | ||||
|         $httplog = "/var/log/apache2/access.log"; | ||||
|     } | ||||
|  | ||||
|     $candidate_log{http}{file} = $httplog; | ||||
|     $candidate_log{http}{type} = $::LOGTYPE_HTTP; | ||||
|  | ||||
|     if ($self->{debug}) { | ||||
|         my $exist_log_file_list; | ||||
|         $exist_log_file_list .= "$candidate_log{$_}{file} " foreach (keys %candidate_log); | ||||
|         probe_utils->send_msg("stdout", "d", "The log files to be scaned are $exist_log_file_list"); | ||||
|     } | ||||
|     return \%candidate_log; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Public function. Obtian logs which belong to a specific second from candidate log files. | ||||
|     Arguments: | ||||
|         the_time_to_load:(input attribute) the specific second. | ||||
|         valid_one_second_log_set_ref: (output attribute) the space which save the vaild logs. A array of reference of hash.  | ||||
|                                       Refer to fucnction "obtain_log_content" for the hash structure of one log. | ||||
|          | ||||
|     Returns: | ||||
|         1: success | ||||
|         0: failed | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_one_second_logs { | ||||
|     my $self                         = shift; | ||||
|     my $the_time_to_load             = shift; | ||||
|     my $valid_one_second_log_set_ref = shift; | ||||
|  | ||||
|     if ($self->{debug}) { | ||||
|         my $logfile = "$self->{debuglogpath}/obtain_one_second_logs.$the_time_to_load"; | ||||
|         my $fd; | ||||
|         open($fd, "> $logfile"); | ||||
|         $self->{debuglogfd} = $fd; | ||||
|     } | ||||
|  | ||||
|     #read log for the first time | ||||
|     #need to find vaild log files and load them | ||||
|     if (!%{ $self->{log_open_info} }) { | ||||
|  | ||||
|         #obtain all exist log files in current server | ||||
|         #such as "/var/log/message, /var/log/xcat/cluster.log......." | ||||
|         my $candidate_log_ref = $self->obtain_log_file_list(); | ||||
|         foreach my $loglabel (keys %$candidate_log_ref) { | ||||
|  | ||||
|             #obtain all rotate log file for one kind of log | ||||
|             #such as "/var/log/message, /var/log/message-20160506, /var/log/message-20160507......." | ||||
|             my $rotate_file_list_ref = $self->obtain_rotate_log_list($candidate_log_ref->{$loglabel}{file}); | ||||
|  | ||||
|             #depending on target log time, find out should read from which rotate log file and which point of this log file | ||||
|             my $read_start_point_ref = $self->obtain_valid_log_start_point($the_time_to_load, $rotate_file_list_ref, $candidate_log_ref->{$loglabel}{type}); | ||||
|  | ||||
|             $self->{log_open_info}->{$loglabel}{rotate_file_list} = $rotate_file_list_ref; | ||||
|             $self->{log_open_info}->{$loglabel}{openning_file_index} = $read_start_point_ref->{log_index}; | ||||
|             $self->{log_open_info}->{$loglabel}{next_read_point} = $read_start_point_ref->{log_start_point}; | ||||
|             $self->{log_open_info}->{$loglabel}{filetype} = $candidate_log_ref->{$loglabel}{type}; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if ($self->{debug}) { | ||||
|         $self->debuglogger("------------Dumper self->{log_open_info}---------------"); | ||||
|         foreach my $loglabel (keys %{ $self->{log_open_info} }) { | ||||
|             $self->debuglogger("[$loglabel]"); | ||||
|             my $rotate_file_list = join(" ", @{ $self->{log_open_info}->{$loglabel}{rotate_file_list} }); | ||||
|             $self->debuglogger("rotate_file_list: $rotate_file_list"); | ||||
|             $self->debuglogger("openning_file_index: $self->{log_open_info}->{$loglabel}{openning_file_index}"); | ||||
|             $self->debuglogger("next_read_point: $self->{log_open_info}->{$loglabel}{next_read_point}"); | ||||
|             $self->debuglogger("filetype: $self->{log_open_info}->{$loglabel}{type}"); | ||||
|             $self->debuglogger("openfd: $self->{log_open_info}->{$loglabel}{openfd}"); | ||||
|         } | ||||
|         $self->debuglogger("--------------------------------------------------------\n"); | ||||
|     } | ||||
|  | ||||
|     foreach my $loglabel (keys %{ $self->{log_open_info} }) { | ||||
|         my $fd; | ||||
|         if (!exists($self->{log_open_info}->{$loglabel}{openfd})) { | ||||
|             if (!open($fd, "$self->{log_open_info}->{$loglabel}{rotate_file_list}->[$self->{log_open_info}->{$loglabel}{openning_file_index}]")) { | ||||
|                 print "[error] open $self->{log_open_info}->{$loglabel}{rotate_file_list}->[$self->{log_open_info}->{$loglabel}{openning_file_index}] failed\n"; | ||||
|                 return 1; | ||||
|             } | ||||
|         } else { | ||||
|             $fd = $self->{log_open_info}->{$loglabel}{openfd}; | ||||
|         } | ||||
|  | ||||
|         if ($fd) { | ||||
|             $self->debuglogger("[read $self->{log_open_info}->{$loglabel}{rotate_file_list}->[$self->{log_open_info}->{$loglabel}{openning_file_index}]]"); | ||||
|             my $next_read_point = $self->{log_open_info}->{$loglabel}{next_read_point}; | ||||
|             my $next_start_time = 0; | ||||
|             my $read_eof        = 1; | ||||
|  | ||||
|             my $i = 0; | ||||
|             for ($i = $self->{log_open_info}->{$loglabel}{openning_file_index} ; $i < @{ $self->{log_open_info}->{$loglabel}{rotate_file_list} } ; $i++) { | ||||
|                 if ($i == $self->{log_open_info}->{$loglabel}{openning_file_index}) { | ||||
|                     seek($fd, $next_read_point, 0); | ||||
|                 } else { | ||||
|                     open($fd, $self->{log_open_info}->{$loglabel}{rotate_file_list}->[$i]); | ||||
|                     $next_read_point = 0; | ||||
|                 } | ||||
|  | ||||
|                 while (<$fd>) { | ||||
|                     chomp; | ||||
|                     $self->debuglogger("[$loglabel]read: $_"); | ||||
|                     my $log_content_ref = $self->obtain_log_content($self->{log_open_info}->{$loglabel}{filetype}, $_); | ||||
|  | ||||
|                     #if read the log whoes time bigger than target time, stop to read | ||||
|                     $self->debuglogger("\t$log_content_ref->{time}   $the_time_to_load"); | ||||
|                     if ($log_content_ref->{time} > $the_time_to_load) { | ||||
|                         $next_start_time = $log_content_ref->{time}; | ||||
|                         $read_eof        = 0; | ||||
|                         $self->debuglogger("\tlast"); | ||||
|                         last; | ||||
|                     } else { | ||||
|  | ||||
|                         #if read the log whoes time is equal the target time, save it | ||||
|                         push @$valid_one_second_log_set_ref, $log_content_ref; | ||||
|  | ||||
|                         #adjust the next read point to next line | ||||
|                         my $len = length($_) + 1; | ||||
|                         $next_read_point += $len; | ||||
|                         $self->debuglogger("\tnext_read_point + $len"); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if ($read_eof) { | ||||
|  | ||||
|                     #reach the end of current openning file, maybe there are vaild log in next rotate file, | ||||
|                     #prepare to search next rotate file | ||||
|                     close($fd); | ||||
|                     $self->debuglogger("\tread_eof"); | ||||
|                 } else { | ||||
|  | ||||
|                     #have found all vaild log in current openning fd | ||||
|                     $self->{log_open_info}->{$loglabel}{openfd} = $fd; | ||||
|                     $self->{log_open_info}->{$loglabel}{openning_file_index} = $i; | ||||
|                     $self->{log_open_info}->{$loglabel}{next_read_point} = $next_read_point; | ||||
|                     $self->{log_open_info}->{$loglabel}{next_start_time} = $next_start_time; | ||||
|                     $self->debuglogger("\tfound all vaild log"); | ||||
|                     last; | ||||
|                 } | ||||
|             }    #end ratate_files loop | ||||
|  | ||||
|             if ($i == @{ $self->{log_open_info}->{$loglabel}{rotate_file_list} } && $read_eof == 1) { | ||||
|                 $self->{log_open_info}->{$loglabel}{openfd} = 0; | ||||
|                 $self->{log_open_info}->{$loglabel}{next_start_time} = 9999999999; | ||||
|                 $self->debuglogger("read out all rotate files"); | ||||
|             } | ||||
|         }    #end $fd | ||||
|     }    #end log_open_info loop | ||||
|  | ||||
|     #delete duplicate logs | ||||
|     $self->delete_duplicate_log($valid_one_second_log_set_ref); | ||||
|  | ||||
|     if ($self->{debug}) { | ||||
|         close($self->{debuglogfd}); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Private function. Depending on target log file name, obtain all related rotated log files. | ||||
|         For example, if the target file is '/var/log/messages', the function should return all rotated '/var/log/messages' files. | ||||
|         Such as '/var/log/messages-20160101', '/var/log/messages-20160102'......... | ||||
|         The all related log files should save into a array in order, the latest log file should be in the tail and the oldest one is in the head of array. | ||||
|         For example, the array should look like ("/var/log/messages-20160103", "/var/log/messages-20160104", "/var/log/messages-20160105", "/var/log/messages"); | ||||
|         Finally, this function return the reference of the array. | ||||
|  | ||||
|     Arguments: | ||||
|         file_name: (input attribute) the target log file name, including full path. | ||||
|         rotate_file_list_ref: (output attibute) the reference of the array which include all related log files name. | ||||
|     Returns: | ||||
|         0: success | ||||
|         1: failed | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_rotate_log_list { | ||||
|     my $self      = shift; | ||||
|     my $file_name = shift; | ||||
|  | ||||
|     my @files     = (); | ||||
|     my $file_path = dirname($file_name); | ||||
|  | ||||
|     my @files_all = glob("$file_path/*"); | ||||
|  | ||||
|     my @files_grep = grep /$file_name.+\d$/, @files_all; | ||||
|  | ||||
|     @files = sort { -M "$b" <=> -M "$a" } @files_grep; | ||||
|  | ||||
|     push @files, $file_name; | ||||
|  | ||||
|     return \@files; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|        Private function. Depending on the reference start time. go through all rotate file list, find out where should start to read log. | ||||
|        I.e. start from which point of which log file. | ||||
|  | ||||
|     Arguments: | ||||
|         start_time: (input attribute) the target start time. | ||||
|         rotate_file_list_ref: (input attibute) the reference of the array which include all related log files name. | ||||
|         log_type: (input attribute) The type of log file | ||||
|  | ||||
|     Returns: | ||||
|         start_point: a hash which include the index of start file and the start point of the file | ||||
|                      %start_point{log_index}: the index of start file in the rotate file list | ||||
|                      %start_point{log_start_point}: where start to read log from. this value will be used by "seek" function | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_valid_log_start_point { | ||||
|     my $self                 = shift; | ||||
|     my $start_time           = shift; | ||||
|     my $rotate_file_list_ref = shift; | ||||
|     my $log_type             = shift; | ||||
|  | ||||
|     my %start_point; | ||||
|     my @files      = @{$rotate_file_list_ref}; | ||||
|     my $list_index = @files - 1; | ||||
|  | ||||
|     my $fd; | ||||
|     my $file; | ||||
|     my $filetype; | ||||
|     my $line; | ||||
|  | ||||
|     $start_point{log_index}       = 0; | ||||
|     $start_point{log_start_point} = 0; | ||||
|     while (@files) { | ||||
|         $file     = pop(@files); | ||||
|         $filetype = `file $file 2>&1`; | ||||
|         chomp($filetype); | ||||
|         if (!open($fd, "$file")) { | ||||
|             print "open $file failed\n"; | ||||
|             $list_index--; | ||||
|             next; | ||||
|         } | ||||
|  | ||||
|         if ($line = <$fd>) { | ||||
|             my %log_content = %{ $self->obtain_log_content($log_type, $line, 0) }; | ||||
|             if ($start_time <= $log_content{time}) { | ||||
|                 $list_index--; | ||||
|                 next; | ||||
|             } else { | ||||
|                 $start_point{log_index} = $list_index; | ||||
|                 seek($fd, 0, 2); | ||||
|                 my $tail           = tell; | ||||
|                 my $head           = 0; | ||||
|                 my $lasttail       = $tail; | ||||
|                 my $file_tail      = $tail; | ||||
|                 my $tmp_start_time = $start_time - 1; | ||||
|                 my $historynum     = 0; | ||||
|  | ||||
|                 while ($head <= $tail) { | ||||
|                     my $middle = int(($tail - $head) / 2) + $head; | ||||
|                     seek($fd, $middle, 0); | ||||
|                     $line = <$fd>; | ||||
|                     $middle += length($line); | ||||
|                     last unless ($line = <$fd>); | ||||
|                     my %log_content = %{ $self->obtain_log_content($log_type, $line, 0) }; | ||||
|                     if ($tmp_start_time == $log_content{time}) { | ||||
|                         $historynum = $middle; | ||||
|                         last; | ||||
|                     } elsif ($tmp_start_time < $log_content{time}) { | ||||
|                         $tail = $middle; | ||||
|                         last if ($tail == $lasttail); | ||||
|                         $lasttail = $tail; | ||||
|                     } else { | ||||
|                         $head = $middle; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 $historynum = $head unless ($historynum); | ||||
|  | ||||
|                 while ($historynum < $file_tail) { | ||||
|                     seek($fd, $historynum, 0); | ||||
|                     $line = <$fd>; | ||||
|                     my %log_content = %{ $self->obtain_log_content($log_type, $line, 0) }; | ||||
|                     if ($start_time <= $log_content{time}) { | ||||
|                         last; | ||||
|                     } elsif ($start_time > $log_content{time}) { | ||||
|                         $historynum += length($line); | ||||
|                     } | ||||
|                 } | ||||
|                 $start_point{log_start_point} = $historynum; | ||||
|                 last; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return \%start_point; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Convert one line original log which comes from log file to a hash.  | ||||
|  | ||||
|     Arguments: | ||||
|         log_type     :(input attribute) valid log type are $::LOGTYPE_RSYSLOG and $::LOGTYPE_HTTP  | ||||
|         original_log :(input attribute) one line log in real log file | ||||
|  | ||||
|     Returns: | ||||
|         log_content_ref: (output attribute) the reference of a hash structure | ||||
|  | ||||
|         The hash structure which contain log message is | ||||
|         %log_content | ||||
|         $log_content{time}   : the timestamp of log, the format is epoch_seconds | ||||
|         $log_content{sender} : the sender of log | ||||
|         $log_content{label}  : the label of log, such as $::LOGLABEL_DHCPD, $::LOGLABEL_TFTP.... refer to "probe_golbal_constant" for all kinds vaild labels  | ||||
|         $log_content{msg}    : the main message of log | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_log_content { | ||||
|     my $self         = shift; | ||||
|     my $log_type     = shift; | ||||
|     my $original_log = shift; | ||||
|  | ||||
|     my %log_content = (); | ||||
|     my $sender; | ||||
|     my @split_line = split(/\s+/, $original_log); | ||||
|  | ||||
|     if ($log_type == $::LOGTYPE_RSYSLOG) { | ||||
|         if ($split_line[0] =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.+)-(.+)/) { | ||||
|             $log_content{time} = $self->convert_to_epoch_seconds($split_line[0]); | ||||
|             $log_content{sender} = $split_line[1]; | ||||
|             if ($split_line[2] =~ /dhcpd/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_DHCPD; | ||||
|             } elsif ($split_line[2] =~ /in.tftpd/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_TFTP; | ||||
|             } elsif ($split_line[2] =~ /^xcat/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_XCAT; | ||||
|             } else { | ||||
|                 $log_content{label} = $::LOGLABEL_UNDEF; | ||||
|             } | ||||
|             $log_content{msg} = join(" ", @split_line[ 3 .. @split_line - 1 ]); | ||||
|         } else { | ||||
|             my $timestamp = join(" ", @split_line[ 0 .. 2 ]); | ||||
|             $log_content{time}   = $self->convert_to_epoch_seconds($timestamp); | ||||
|             $log_content{sender} = $split_line[3]; | ||||
|             if ($split_line[4] =~ /dhcpd/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_DHCPD; | ||||
|             } elsif ($split_line[4] =~ /in.tftpd/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_TFTP; | ||||
|             } elsif ($split_line[4] =~ /^xcat/i) { | ||||
|                 $log_content{label} = $::LOGLABEL_XCAT; | ||||
|             } else { | ||||
|                 $log_content{label} = $::LOGLABEL_UNDEF; | ||||
|             } | ||||
|             $log_content{msg} = join(" ", @split_line[ 5 .. @split_line - 1 ]); | ||||
|         } | ||||
|     } elsif ($log_type == $::LOGTYPE_HTTP) { | ||||
|         $split_line[3] =~ s/^\[(.+)/$1/g; | ||||
|         $log_content{time}   = $self->convert_to_epoch_seconds($split_line[3]); | ||||
|         $log_content{sender} = $split_line[0]; | ||||
|         $log_content{label}  = $::LOGLABEL_HTTP; | ||||
|         $log_content{msg}    = join(" ", @split_line[ 5 .. @split_line - 1 ]); | ||||
|     } | ||||
|     return \%log_content; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Convert input time format to the number of non-leap seconds since whatever time the system considers to be the epoch | ||||
|     Arguments: | ||||
|         timestr: the time format need to be converted | ||||
|     Returns: | ||||
|         the number of non-leap seconds since whatever time the system considers to be the epoch | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub convert_to_epoch_seconds { | ||||
|     my $self    = shift; | ||||
|     my $timestr = shift; | ||||
|  | ||||
|     my $yday; | ||||
|     my $mday; | ||||
|     my $dday; | ||||
|     my $h; | ||||
|     my $m; | ||||
|     my $s; | ||||
|     my $epoch_seconds = -1; | ||||
|     my %monthsmap = ("Jan" => 0, "Feb" => 1, "Mar" => 2, "Apr" => 3, "May" => 4, "Jun" => 5, "Jul" => 6, "Aug" => 7, "Sep" => 8, "Oct" => 9, "Nov" => 10, "Dec" => 11); | ||||
|  | ||||
|     # The time format looks like "2016-08-29T03:30:18.259287-04:00" | ||||
|     if ($timestr =~ /(\d+)-(\d+)-(\d+)T(\d+):(\d+):(\d+)(.+)-(.+)/) { | ||||
|         ($yday, $mday, $dday, $h, $m, $s) = ($1 + 0, $2 - 1, $3 + 0, $4 + 0, $5 + 0, $6 + 0); | ||||
|         $epoch_seconds = timelocal($s, $m, $h, $dday, $mday, $yday); | ||||
|  | ||||
|         # The time format looks like "Aug 15 02:43:31" | ||||
|     } elsif ($timestr =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/) { | ||||
|         ($mday, $dday, $h, $m, $s) = ($1, $2, $3, $4, $5); | ||||
|         $yday = $self->{current_ref_year}; | ||||
|         $epoch_seconds = timelocal($s, $m, $h, $dday, $monthsmap{$mday}, $yday); | ||||
|         if ($epoch_seconds > $self->{current_ref_time}) { | ||||
|             $yday -= 1; | ||||
|             $epoch_seconds = timelocal($s, $m, $h, $dday, $monthsmap{$mday}, $yday); | ||||
|         } | ||||
|  | ||||
|         # The time format looks like "15/Aug/2016:01:10:24" | ||||
|     } elsif ($timestr =~ /(\d+)\/(\w+)\/(\d+):(\d+):(\d+):(\d+)/) { | ||||
|         $epoch_seconds = timelocal($6, $5, $4, $1, $monthsmap{$2}, ($3 - 1900)); | ||||
|     } | ||||
|     return $epoch_seconds; | ||||
| } | ||||
|  | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Private function. After obtain one second logs. deleted these duplicate logs. | ||||
|     Arguments: | ||||
|         vaild_log_set_ref:(input/output attribute) The reference of the log set which will be scaned to delete duplicate log | ||||
|     Returns: | ||||
|         NULL | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub delete_duplicate_log { | ||||
|     my $self              = shift; | ||||
|     my $vaild_log_set_ref = shift; | ||||
|  | ||||
|     my $log_index = @$vaild_log_set_ref - 1; | ||||
|     my @delete_index; | ||||
|     for (my $i = $log_index ; $i > 0 ; $i--) { | ||||
|         for (my $j = 0 ; $j < $i ; $j++) { | ||||
|             if (($vaild_log_set_ref->[$i]->{time} == $vaild_log_set_ref->[$j]->{time}) && | ||||
|                 ($vaild_log_set_ref->[$i]->{label} == $vaild_log_set_ref->[$j]->{label}) && | ||||
|                 ($vaild_log_set_ref->[$i]->{sender} eq $vaild_log_set_ref->[$j]->{sender}) && | ||||
|                 ($vaild_log_set_ref->[$i]->{msg} eq $vaild_log_set_ref->[$j]->{msg})) { | ||||
|                 if (!grep { $_ eq $i } @delete_index) { | ||||
|                     push @delete_index, $i; | ||||
|                     last; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     foreach (@delete_index) { | ||||
|         my @new_list = (); | ||||
|         splice(@$vaild_log_set_ref, $_, 1, @new_list); | ||||
|     } | ||||
|  | ||||
|     if ($self->{debug}) { | ||||
|         $self->debuglogger("------------After delete duplicate logs---------------"); | ||||
|         foreach my $log_ref (@{$vaild_log_set_ref}) { | ||||
|             $self->debuglogger("$log_ref->{msg}"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Public function. Obtain the next second when should get logs from | ||||
|     Arguments: | ||||
|         NULL | ||||
|     Returns: | ||||
|         The second when should get logs from | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub obtain_next_second { | ||||
|     my $self = shift; | ||||
|  | ||||
|     my $next_start_time = 9999999999; | ||||
|     foreach my $loglabel (keys %{ $self->{log_open_info} }) { | ||||
|         if ($self->{log_open_info}->{$loglabel}{next_start_time} < $next_start_time) { | ||||
|             $next_start_time = $self->{log_open_info}->{$loglabel}{next_start_time}; | ||||
|         } | ||||
|     } | ||||
|     return $next_start_time; | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         The destructor of class 'LogParse' | ||||
|     Arguments: | ||||
|         NULL | ||||
|     Returns: | ||||
|         NULL | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub destory { | ||||
|     my $self = shift; | ||||
|     foreach my $loglabel (keys %{ $self->{log_open_info} }) { | ||||
|         if ($self->{log_open_info}->{$loglabel}{openfd}) { | ||||
|             close($self->{log_open_info}->{$loglabel}{openfd}); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if ($self->{debuglogfd}) { | ||||
|         close($self->{debuglogfd}); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Private function. Used for log debug information to disk.  | ||||
|     Arguments: | ||||
|         $msg : The massage which will be logged into log file.  | ||||
|     Returns: | ||||
|         NULL | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub debuglogger { | ||||
|     my $self = shift; | ||||
|     my $msg  = shift; | ||||
|     if ($self->{debug}) { | ||||
|         my $fd = $self->{debuglogfd}; | ||||
|         print $fd "$msg\n"; | ||||
|     } | ||||
| } | ||||
| 1; | ||||
|  | ||||
							
								
								
									
										47
									
								
								xCAT-probe/lib/perl/probe_global_constant.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								xCAT-probe/lib/perl/probe_global_constant.pm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| #!/usr/bin/env perl | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
| package probe_golbal_constant; | ||||
|  | ||||
| #The type of log | ||||
| $::LOGTYPE_RSYSLOG = 0;    #rsyslog | ||||
| $::LOGTYPE_HTTP    = 1;    #apache log | ||||
|  | ||||
| #The lable of specific line log | ||||
| $::LOGLABEL_DHCPD = 0; | ||||
| $::LOGLABEL_TFTP  = 1; | ||||
| $::LOGLABEL_HTTP  = 2; | ||||
| $::LOGLABEL_XCAT  = 3; | ||||
| $::LOGLABEL_UNDEF = 4; | ||||
|  | ||||
| #The important stage of provision process | ||||
| $::STATE_POWER_ON       = 1; | ||||
| $::STATE_POWERINGON     = 2; | ||||
| $::STATE_DHCP           = 3; | ||||
| $::STATE_BOOTLODER      = 4; | ||||
| $::STATE_KERNEL         = 5; | ||||
| $::STATE_INITRD         = 6; | ||||
| $::STATE_KICKSTART      = 7; | ||||
| $::STATE_INSTALLING     = 8; | ||||
| $::STATE_INSTALLRPM     = 9; | ||||
| $::STATE_POSTSCRIPT     = 10; | ||||
| $::STATE_BOOTING        = 11; | ||||
| $::STATE_POSTBOOTSCRIPT = 12; | ||||
| $::STATE_COMPLETED      = 13; | ||||
|  | ||||
| #The description of every important stage of provision process | ||||
| %::STATE_DESC = ( | ||||
|     $::STATE_POWER_ON       => "rpower_to_install", | ||||
|     $::STATE_POWERINGON     => "powering_on", | ||||
|     $::STATE_DHCP           => "got_ip_from_dhcp", | ||||
|     $::STATE_BOOTLODER      => "download_bootloder", | ||||
|     $::STATE_KERNEL         => "download_kernel", | ||||
|     $::STATE_INITRD         => "download_initrd", | ||||
|     $::STATE_KICKSTART      => "download_kickstart", | ||||
|     $::STATE_INSTALLING     => "installing", | ||||
|     $::STATE_INSTALLRPM     => "start_to_install_os_package", | ||||
|     $::STATE_POSTSCRIPT     => "running_postscripts", | ||||
|     $::STATE_BOOTING        => "booting", | ||||
|     $::STATE_POSTBOOTSCRIPT => "running_postbootscripts", | ||||
|     $::STATE_COMPLETED      => "complete", | ||||
| ); | ||||
| 1; | ||||
| @@ -16,13 +16,19 @@ use Socket; | ||||
|         Format is [<flag>] : <message> | ||||
|         The valid <flag> are debug, warning, failed, info and ok | ||||
|     Arguments: | ||||
|         output: where should output the message  | ||||
|         num:  the number of <flag> | ||||
|         output: where should the message be output  | ||||
|               The vaild value are: | ||||
|               stdout : print message to STDOUT | ||||
|               a file name: print message to the file which "file name" specify  | ||||
|         tag:  the type of message, the valid value are: | ||||
|               d: debug | ||||
|               w: warning | ||||
|               f: failed | ||||
|               o: ok | ||||
|               i: info | ||||
|  | ||||
|               if tag is NULL, that means output message without tag | ||||
|               | ||||
|         msg:  the information need to output | ||||
|      Returns: | ||||
|         1 : Failed  | ||||
| @@ -35,7 +41,7 @@ sub send_msg { | ||||
|     $output = shift if (($output) && ($output =~ /probe_utils/)); | ||||
|     my $tag = shift; | ||||
|     my $msg = shift; | ||||
|     my $flag; | ||||
|     my $flag=""; | ||||
|  | ||||
|     if ($tag eq "d") { | ||||
|         $flag = "[debug]  :"; | ||||
| @@ -516,4 +522,25 @@ sub convert_to_epoch_seconds { | ||||
|     } | ||||
|     return $epoch_seconds; | ||||
| } | ||||
|  | ||||
|  | ||||
| #------------------------------------------ | ||||
|  | ||||
| =head3 | ||||
|     Description: | ||||
|         Convert node range in Regular Expression to a node name array | ||||
|     Arguments: | ||||
|         noderange : the range of node | ||||
|     Returns: | ||||
|         A array which contain each node name | ||||
| =cut | ||||
|  | ||||
| #------------------------------------------ | ||||
| sub parse_node_range { | ||||
|     my $noderange = shift; | ||||
|     $noderange= shift if (($noderange) && ($noderange =~ /probe_utils/)); | ||||
|     my @nodeslist = `nodels $noderange`; | ||||
|     chomp($_) foreach(@nodeslist); | ||||
|     return @nodeslist; | ||||
| } | ||||
| 1; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user