mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-06-14 02:10:23 +00:00
implement discovery basic function
This commit is contained in:
@ -5,7 +5,7 @@ package probe_utils;
|
||||
use strict;
|
||||
use File::Path;
|
||||
use File::Copy;
|
||||
|
||||
use Socket;
|
||||
#-----------------------------------------
|
||||
|
||||
=head3
|
||||
@ -341,4 +341,102 @@ sub is_dns_ready {
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Convert host name to ip address
|
||||
Arguments:
|
||||
hostname: The hostname need to convert
|
||||
Returns:
|
||||
ip: The ip address
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub get_ip_from_hostname{
|
||||
my $hostname = shift;
|
||||
$hostname=shift if(($hostname) && ($hostname =~ /probe_utils/));
|
||||
my $ip = "";
|
||||
|
||||
my @output = `ping -c 1 $hostname 2>&1`;
|
||||
if(!$?){
|
||||
if($output[0] =~ /^PING.+\s+\((\d+\.\d+\.\d+\.\d+)\).+/){
|
||||
$ip=$1;
|
||||
}
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Calculate network address from ip and netmask
|
||||
Arguments:
|
||||
ip: ip address
|
||||
mask: network mask
|
||||
Returns:
|
||||
network : The network address
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub get_network{
|
||||
my $ip = shift;
|
||||
$ip=shift if(($ip) && ($ip =~ /probe_utils/));
|
||||
my $mask = shift;
|
||||
my $net="";
|
||||
|
||||
return $net if (!is_ip_addr($ip));
|
||||
return $net if ($mask !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
||||
|
||||
my $bin_mask = 0;
|
||||
$bin_mask = (($1 + 0) << 24) + (($2 + 0) << 16) + (($3 + 0) << 8) + ($4 + 0) if ($mask =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
||||
|
||||
my $bin_ip = 0;
|
||||
$bin_ip = (($1 + 0) << 24) + (($2 + 0) << 16) + (($3 + 0) << 8) + ($4 + 0) if ($ip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/);
|
||||
|
||||
my $net_int32 = $bin_mask & $bin_ip;
|
||||
$net = ($net_int32 >> 24) . "." . (($net_int32 >> 16) & 0xff) . "." . (($net_int32 >> 8) & 0xff) . "." . ($net_int32 & 0xff);
|
||||
return "$net/$mask";
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Convert ip to hostname
|
||||
Arguments:
|
||||
ip: The ip need to convert
|
||||
Returns:
|
||||
hostname: hostname or ""
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub get_hostname_from_ip{
|
||||
my $ip = shift;
|
||||
$ip=shift if(($ip) && ($ip =~ /probe_utils/));
|
||||
my $dns_server = shift;
|
||||
my $hostname="";
|
||||
my $output="";
|
||||
|
||||
`which nslookup > /dev/null 2>&1`;
|
||||
if(!$?){
|
||||
$output = `nslookup $ip $dns_server 2>&1`;
|
||||
if (!$?) {
|
||||
chomp($output);
|
||||
my $rc = $hostname = `echo "$output"|awk -F" " '/name =/ {print \$4}'|awk -F"." '{print \$1}'`;
|
||||
chomp($hostname);
|
||||
return $hostname if (!$rc);
|
||||
}
|
||||
}
|
||||
if(($hostname eq "") && (-e "/etc/hosts")){
|
||||
$output = `cat /etc/hosts 2>&1 |grep $ip`;
|
||||
if(!$?){
|
||||
my @splitoutput = split(" ", $output);
|
||||
$hostname = $splitoutput[1];
|
||||
}
|
||||
}
|
||||
return $hostname;
|
||||
}
|
||||
|
||||
1;
|
||||
|
@ -6,38 +6,71 @@ BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/o
|
||||
use lib "$::XCATROOT/probe/lib/perl";
|
||||
use probe_utils;
|
||||
use File::Basename;
|
||||
use IO::Select;
|
||||
use Getopt::Long qw(:config no_ignore_case);
|
||||
use Data::Dumper;
|
||||
|
||||
my $program_name = basename("$0");
|
||||
my $help;
|
||||
my $test;
|
||||
my $output = "stdout";
|
||||
my $verbose = 0;
|
||||
my $rst = 0;
|
||||
my $output = "stdout";
|
||||
my $verbose = 0;
|
||||
my $rst = 0;
|
||||
my $pre_check = 0;
|
||||
my $monitor = 0;
|
||||
my $discovery_type;
|
||||
my @valid_discovery_type = ("mtms", "switch");
|
||||
my $valid_discovery_type_str = join(",", @valid_discovery_type);
|
||||
my $noderange;
|
||||
my $nics;
|
||||
|
||||
#used for discovery monitor
|
||||
my %rawdata;
|
||||
my %ipmacmap;
|
||||
my $terminal = 0;
|
||||
my %monitor_nodes;
|
||||
|
||||
$::USAGE = "Usage:
|
||||
$program_name -h
|
||||
$program_name -t
|
||||
$program_name [-V]
|
||||
$program_name -s
|
||||
$program_name -p [-V] [-T <discovery_type>] [-n <node_range>]
|
||||
$program_name -m
|
||||
$program_name [-V] [-T <discovery_type>] [-n <node_range>]
|
||||
|
||||
Description:
|
||||
Check discovery files or process.
|
||||
Do probe for discovery process, including pro-check for required configuration and realtime monitor of discovery process.
|
||||
If without any option, $program_name will do pro-check first, if all checking point pass, then goes to monitor directly.
|
||||
|
||||
Options:
|
||||
-h : Get usage information of $program_name
|
||||
-t : To verify if $program_name can work, reserve option for probe framework
|
||||
-V : Output more information for debug
|
||||
-s : Discovery static check, check whether genesis files are ready
|
||||
-h : Get usage information of $program_name.
|
||||
-t : To verify if $program_name can work, reserve option for probe framework.
|
||||
-V : Output more information for debug.
|
||||
-p : Do pre-check for disvoery, check whether required configuration have been done ahead.
|
||||
-T : The type of discovery, the valid values are $valid_discovery_type_str.
|
||||
-n : The range of predefined node, must used with option -m.
|
||||
-m : Do realtime monitor for discovery process.
|
||||
";
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Check if all genesis files are available.
|
||||
Arguments:
|
||||
arch: valid value are ppc64 and x86_64
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub check_genesis_file {
|
||||
my $arch = shift;
|
||||
my $arch = shift;
|
||||
if (($arch ne "ppc64") and ($arch ne "x86_64")) {
|
||||
probe_utils->send_msg("$output", "f", "Please input correct arch type");
|
||||
probe_utils->send_msg("$output", "d", "Please input correct arch type") if ($verbose);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
my $rst_f = 0;
|
||||
probe_utils->send_msg("$output", "d", "Start to check genesis files for $arch...") if ($verbose);
|
||||
|
||||
@ -229,14 +262,669 @@ sub check_genesis_file {
|
||||
return $rst_f;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
1. check if there are dynamic range for specific networks defineded in dhcp conf file
|
||||
2. check if these specific networks have corresponding genesis configuration
|
||||
Arguments:
|
||||
networks: A Comma separated list of networks. Every network is combined by network address and mask(i.e. network/mask).
|
||||
For example: 10.0.0.0/255.0.0.0,50.1.0.0/255.255.0.0
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub dhcp_dynamic_range_check {
|
||||
my $nets = shift;
|
||||
my $rst = 0;
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Handle one line log come from tftp log file
|
||||
Arguments:
|
||||
msg: one line tftp log
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub handle_tftp_msg {
|
||||
my $msg = shift;
|
||||
if ($msg =~ /RRQ\s+from\s+(.+)\s+filename\s+(.+)/i) {
|
||||
my $ip = $1;
|
||||
my $file = $2;
|
||||
my $record = "Via TFTP $ip download $file";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{"$ipmacmap{$ip}"})) {
|
||||
|
||||
#push(@{$rawdata{$ipmacmap{$ip}}{"history"}}, $record) unless (/^$record$/ ~~ @{$rawdata{$ipmacmap{$ip}}{"history"}});
|
||||
push(@{ $rawdata{ $ipmacmap{$ip} }{"history"} }, $record);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Handle one line log come from http log file
|
||||
Arguments:
|
||||
msg: one line http log
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub handle_http_msg {
|
||||
my $msg = shift;
|
||||
if ($msg =~ /(\d+\.\d+.\d+.\d+)\s.+GET\s+(.+)\s+HTTP.+/) {
|
||||
my $ip = $1;
|
||||
my $file = $2;
|
||||
my $record = "Via HTTP $ip download $file";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{"$ipmacmap{$ip}"})) {
|
||||
push(@{ $rawdata{ $ipmacmap{$ip} }{"history"} }, $record);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Handle one line log come from dhcp log file
|
||||
Arguments:
|
||||
msg: one line http log
|
||||
nics: target network interfaces
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub handle_dhcp_msg {
|
||||
my $msg = shift;
|
||||
my $nics = shift;
|
||||
my @nicarray = split(",", $nics);
|
||||
if ($msg =~ /.+DHCPDISCOVER\s+from\s+(.+)\s+via\s+(.+)/i) {
|
||||
my @tmpmsg = split(" ", $msg);
|
||||
my $mac = $tmpmsg[7];
|
||||
my $nic = $tmpmsg[9];
|
||||
$nic =~ s/(.+):/$1/g if ($nic =~ /:$/);
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
if ($msg =~ /no free leases/) {
|
||||
probe_utils->send_msg("$output", "d", "Receive DHCPDISCOVER from $mac via $nic, no free leases");
|
||||
return 0;
|
||||
}
|
||||
my $record = "Receive DHCPDISCOVER from $mac via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (!exists($rawdata{$mac})) {
|
||||
my @history;
|
||||
push(@history, $record);
|
||||
$rawdata{$mac}{"history"} = \@history;
|
||||
} else {
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
}
|
||||
} elsif ($msg =~ /.+DHCPOFFER\s+on\s+(.+)\s+to\s+(.+)\s+via\s+(.+)/i) {
|
||||
my $ip = $1;
|
||||
my $mac = $2;
|
||||
my $nic = $3;
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
my $record = "Send DHCPOFFER on $ip back to $mac via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{$mac})) {
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
}
|
||||
} elsif ($msg !~ /unknown lease/ && $msg !~ /ignored/ && $msg =~ /.+DHCPREQUEST\s+for\s+(.+)\s\((.+)\)\s+from\s+(.+)\s+via\s+(.+)/) {
|
||||
my $ip = $1;
|
||||
my $server = $2;
|
||||
my $mac = $3;
|
||||
my $nic = $4;
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
my $record = "Receive DHCPREQUEST from $mac for $ip via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{$mac})) {
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
}
|
||||
} elsif ($msg =~ /.+DHCPACK\s+on\s+(.+)\s+to\s+(.+)\s+via\s+(.+)/) {
|
||||
my $ip = $1;
|
||||
my $mac = $2;
|
||||
my $nic = $3;
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
my $record = "Send DHCPACK on $ip back to $mac via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{$mac})) {
|
||||
$rawdata{$mac}{"ip"} = $ip;
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
$ipmacmap{$ip} = $mac;
|
||||
}
|
||||
} elsif ($msg =~ /.+BOOTREQUEST\s+from\s+(.+)\s+via\s+(.+)/) {
|
||||
my @tmpmsg = split(" ", $msg);
|
||||
my $mac = $tmpmsg[7];
|
||||
my $nic = $tmpmsg[9];
|
||||
$nic =~ s/(.+):/$1/g if ($nic =~ /:$/);
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
if ($msg =~ /no dynamic leases/) {
|
||||
probe_utils->send_msg("$output", "d", "Receive DHCPDISCOVER from $mac via $nic, no dynamic leases");
|
||||
return 0;
|
||||
}
|
||||
my $record = "Receive BOOTREQUEST from $mac via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (!exists($rawdata{$mac})) {
|
||||
my @history;
|
||||
push(@history, $record);
|
||||
$rawdata{$mac}{"history"} = \@history;
|
||||
} else {
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
}
|
||||
} elsif ($msg =~ /.+BOOTREPLY\s+for\s+(.+)\s+to\s+.+(\w\w:\w\w:\w\w:\w\w:\w\w:\w\w).+via\s+(.+)/) {
|
||||
my $ip = $1;
|
||||
my $mac = $2;
|
||||
my $nic = $3;
|
||||
return 0 unless (@nicarray ~~ /^$nic$/);
|
||||
my $record = "Send BOOTREPLY on $ip back to $mac via $nic";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
if (exists($rawdata{$mac})) {
|
||||
$rawdata{$mac}{"ip"} = $ip;
|
||||
push(@{ $rawdata{$mac}{"history"} }, $record);
|
||||
$ipmacmap{$ip} = $mac;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Handle one line log come from computes.log
|
||||
Arguments:
|
||||
msg: one line compute log
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub handle_compute_msg {
|
||||
|
||||
my $line = shift;
|
||||
my $sender = "";
|
||||
my $ip = "";
|
||||
my $msg;
|
||||
|
||||
my @splitline = split(" ", $line);
|
||||
if (($splitline[4] =~ /^xcat/i) || ($splitline[5] =~ /^xcat/i)) {
|
||||
$sender = $splitline[3];
|
||||
for (my $i = 0 ; $i < 5 ; $i++) {
|
||||
shift(@splitline);
|
||||
}
|
||||
$msg = join(" ", @splitline);
|
||||
if (!probe_utils->is_ip_addr("$sender")) {
|
||||
$ip = probe_utils->get_ip_from_hostname("$sender");
|
||||
} else {
|
||||
$ip = $sender;
|
||||
}
|
||||
if ($ip ne "" && exists($ipmacmap{$ip})) {
|
||||
my $record = "Recv from $ipmacmap{$ip}($ip) : $msg";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
push(@{ $rawdata{ $ipmacmap{$ip} }{"history"} }, $record);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Handle one line log come from cluster.log
|
||||
Arguments:
|
||||
msg: one line log
|
||||
Returns:
|
||||
0 : pass
|
||||
1 : failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub handle_cluster_msg {
|
||||
my $line = shift;
|
||||
my $sender = "";
|
||||
my $ip = "";
|
||||
my $msg;
|
||||
|
||||
if ($line =~ /.+\d+:\d+:\d+\s+(.+)\s+(xcat.+)/i) {
|
||||
$sender = $1;
|
||||
$msg = $2;
|
||||
if (!probe_utils->is_ip_addr("$sender")) {
|
||||
$ip = probe_utils->get_ip_from_hostname("$sender");
|
||||
} else {
|
||||
$ip = $sender;
|
||||
}
|
||||
if ($ip ne "" && exists($ipmacmap{$ip})) {
|
||||
my $record = "Recv from $ipmacmap{$ip}($ip) : $msg";
|
||||
probe_utils->send_msg("$output", "d", "$record");
|
||||
push(@{ $rawdata{ $ipmacmap{$ip} }{"history"} }, $record);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Dump monitor history, categorised by mac address.
|
||||
Arguments:
|
||||
NULL
|
||||
Returns:
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub dump_history {
|
||||
probe_utils->send_msg("$output", "d", "=======================================");
|
||||
probe_utils->send_msg("$output", "d", "= The summary of discovery:");
|
||||
probe_utils->send_msg("$output", "d", "=======================================");
|
||||
|
||||
my $masterip = `tabdump site 2>&1 | awk -F',' '/master/ { gsub(/"/, "", \$2) ; print \$2 }'`;
|
||||
chomp($masterip);
|
||||
foreach $mac (keys %rawdata) {
|
||||
my $nodehostname = probe_utils->get_hostname_from_ip($rawdata{$mac}{"ip"}, $masterip);
|
||||
if ($nodehostname ne "") {
|
||||
probe_utils->send_msg("$output", "d", "[$mac ($nodehostname)]");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "d", "[$mac]:");
|
||||
}
|
||||
foreach my $line (@{ $rawdata{$mac}{"history"} }) {
|
||||
probe_utils->send_msg("$output", "d", "| $line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Check if all predefined node are valid
|
||||
Arguments:
|
||||
discovery_type: valid value are mtms and switch
|
||||
noderange: node range
|
||||
Returns:
|
||||
0: pass
|
||||
1: failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub check_pre_defined_node {
|
||||
my $discovery_type = shift;
|
||||
my $noderange = shift;
|
||||
|
||||
my $rst = 0;
|
||||
my @cmdoutput;
|
||||
my %nodecheckrst;
|
||||
my $currentnode = "";
|
||||
|
||||
@cmdoutput = `lsdef $noderange 2>&1`;
|
||||
foreach (@cmdoutput) {
|
||||
if ($_ =~ /^Error: Could not find an object named '(\w+)' .+/i) {
|
||||
$currentnode = $1;
|
||||
$nodecheckrst{$currentnode}{"error"} = "Could not find node definition";
|
||||
$rst = 1;
|
||||
} elsif ($_ =~ /^\s*Object name: (\w+)/i) {
|
||||
$currentnode = $1;
|
||||
} elsif ($_ =~ /^\s+(\w+)\s*=\s*(\w+)/) {
|
||||
$nodecheckrst{$currentnode}{$1} = $2;
|
||||
}
|
||||
}
|
||||
|
||||
#print Dumper(%nodecheckrst);
|
||||
|
||||
foreach my $node (keys %nodecheckrst) {
|
||||
if (!exists($nodecheckrst{$node}{error})) {
|
||||
if ($discovery_type eq "mtms") {
|
||||
if (exists($nodecheckrst{$node}{"mtm"}) && exists($nodecheckrst{$node}{"serial"})) {
|
||||
$nodecheckrst{$node}{"error"} = "node definition is good for '$discovery_type' type discovery";
|
||||
} else {
|
||||
$nodecheckrst{$node}{"error"} = "node definition is wrong for '$discovery_type' type discovery";
|
||||
$rst = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($discovery_type eq "switch") {
|
||||
if (exists($nodecheckrst{$node}{"switch"}) && exists($nodecheckrst{$node}{"switchport"})) {
|
||||
$nodecheckrst{$node}{"error"} = "node definition is good for '$discovery_type' type discovery";
|
||||
} else {
|
||||
$nodecheckrst{$node}{"error"} = "node definition is wrong for '$discovery_type' type discovery";
|
||||
$rst = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($verbose) {
|
||||
foreach my $node (keys %nodecheckrst) {
|
||||
probe_utils->send_msg("$output", "d", "$node : $nodecheckrst{$node}{error}");
|
||||
}
|
||||
}
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Get monitor nodes list
|
||||
Arguments:
|
||||
One golble attribute %monitor_nodes;
|
||||
Returns:
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub get_monitor_nodes_list {
|
||||
my @cmdoutput = `lsdef $noderange 2>&1`;
|
||||
foreach (@cmdoutput) {
|
||||
if ($_ =~ /^Error: Could not find an object named '(\w+)' .+/i) {
|
||||
$monitor_nodes{$1} = 0;
|
||||
} elsif ($_ =~ /^\s*Object name: (\w+)/i) {
|
||||
$monitor_nodes{$1} = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Test if all nodes have finished job
|
||||
Arguments:
|
||||
One golble attribute %monitor_nodes;
|
||||
Returns:
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub all_monitor_node_done {
|
||||
my $done = 1;
|
||||
foreach my $node (keys %monitor_nodes) {
|
||||
$done = 0 if ($monitor_nodes{$node} == 0);
|
||||
}
|
||||
return $done;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Do pre_checking
|
||||
Arguments:
|
||||
nics: target network interface
|
||||
if not specified, using the network which master belongs to
|
||||
Returns:
|
||||
0: pass
|
||||
1: failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub do_pre_check {
|
||||
my $nics = shift;
|
||||
my @nets = ();
|
||||
my $rst = 0;
|
||||
my $msg;
|
||||
|
||||
if (defined($noderange) && defined($discovery_type)) {
|
||||
$msg = "All pre_defined nodes are valid";
|
||||
my $rc = check_pre_defined_node($discovery_type, $noderange);
|
||||
if ($rc) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
$rst = 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($nics) {
|
||||
if ($nics =~ /[^\w,]/) {
|
||||
probe_utils->send_msg("$output", "f", "Invalid NIC list");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
$msg = "The input network interfaces $nics exist and are configured well on current server";
|
||||
my $miss = 0;
|
||||
my @nic_array = split(",", $nics);
|
||||
foreach my $nic (@nic_array) {
|
||||
my $tmp_nic = `ip addr show $nic >/dev/null 2>&1`;
|
||||
if ($?) {
|
||||
probe_utils->send_msg("$output", "d", "Network interface $nic doesn't exist on current server") if ($verbose);
|
||||
$miss = 1;
|
||||
} else {
|
||||
my $tmp = `ifconfig $nic|awk -F" " '/inet / {print \$2,\$4}'`;
|
||||
chomp($tmp);
|
||||
if (!$tmp) {
|
||||
probe_utils->send_msg("$output", "d", "Network interface $nic isn't set IP address") if ($verbose);
|
||||
$miss = 1;
|
||||
} else {
|
||||
my ($ip, $mask) = split(" ", $tmp);
|
||||
push(@nets, probe_utils->get_network($ip, $mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($miss) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
$rst = 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
}
|
||||
} else {
|
||||
$msg = "Attribute 'master' in 'site' table is configured well";
|
||||
my $masteripinsite = `tabdump site | awk -F',' '/master/ { gsub(/"/, "", \$2) ; print \$2 }'`;
|
||||
chomp($masteripinsite);
|
||||
if ($masteripinsite eq "") {
|
||||
probe_utils->send_msg("$output", "d", "There isn't 'master' definition in 'site' talbe") if ($verbose);
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
exit 1;
|
||||
}
|
||||
if (!probe_utils->is_ip_addr("$masteripinsite")) {
|
||||
probe_utils->send_msg("$output", "d", "The value of 'master' in 'site' table isn't a IP address") if ($verbose);
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
exit 1;
|
||||
}
|
||||
`ifconfig -a 2>&1 |grep $masteripinsite`;
|
||||
if ($?) {
|
||||
probe_utils->send_msg("$output", "d", "The IP $masteripinsite of 'master' in 'site' table dosen't belong to any network on current server") if ($verbose);
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
exit 1;
|
||||
}
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
my $tmp = `ifconfig -a|awk -F" " '/$masteripinsite/ {print \$2,\$4}'`;
|
||||
chomp($tmp);
|
||||
my ($ip, $mask) = split(" ", $tmp);
|
||||
push(@nets, probe_utils->get_network($ip, $mask));
|
||||
}
|
||||
|
||||
my $arch = `uname -i`;
|
||||
chomp($arch);
|
||||
$msg = "Genesis files for $arch are available";
|
||||
if ($arch =~ /ppc64/i) {
|
||||
if (check_genesis_file("ppc64")) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
$rst = 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
if (check_genesis_file("x86_64")) {
|
||||
probe_utils->send_msg("$output", "w", "Genesis files for x86 are not available");
|
||||
probe_utils->send_msg("$output", "i", "If don't plan to manage a x86 server, please ignore above warning");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", "Genesis files for x86 are available");
|
||||
}
|
||||
}
|
||||
} elsif ($arch =~ /x86/i) {
|
||||
if (check_genesis_file("x86_64")) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
$rst = 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
if (check_genesis_file("ppc64")) {
|
||||
probe_utils->send_msg("$output", "w", "Genesis files for ppc64/ppc64le are not available");
|
||||
probe_utils->send_msg("$output", "i", "If don't plan to manage a ppc64/ppc64le server, please ignore above warning");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", "Genesis files for ppc64/ppc64le are available");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$msg = "DHCP dynamic range is configured well";
|
||||
if (dhcp_dynamic_range_check(\@nets)) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
$rst = 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
}
|
||||
|
||||
return $rst;
|
||||
}
|
||||
|
||||
#------------------------------------------
|
||||
|
||||
=head3
|
||||
Description:
|
||||
Monitor the process of discovery
|
||||
Arguments:
|
||||
nics: target network interface
|
||||
if not specified, using the network which master belongs to
|
||||
Returns:
|
||||
0: pass
|
||||
1: failed
|
||||
=cut
|
||||
|
||||
#------------------------------------------
|
||||
sub do_monitor {
|
||||
$SIG{TERM} = $SIG{INT} = sub {
|
||||
$terminal = 1;
|
||||
};
|
||||
|
||||
if ($monitor && !$pre_check && defined($noderange) && defined($discovery_type)) {
|
||||
$msg = "All pre_defined nodes are valid";
|
||||
my $rc = check_pre_defined_node($discovery_type, $noderange);
|
||||
if ($rc) {
|
||||
probe_utils->send_msg("$output", "f", $msg);
|
||||
exit 1;
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", $msg);
|
||||
}
|
||||
}
|
||||
|
||||
&get_monitor_nodes_list if (defined($noderange) && defined($discovery_type));
|
||||
|
||||
if (!$nics) {
|
||||
my $masteripinsite = `tabdump site | awk -F',' '/master/ { gsub(/"/, "", \$2) ; print \$2 }'`;
|
||||
chomp($masteripinsite);
|
||||
$nics = `ip addr |grep -B2 $masteripinsite|awk -F" " '/mtu/{gsub(/:/,"",\$2); print \$2}'`;
|
||||
chomp($nics);
|
||||
if (!$nics) {
|
||||
probe_utils->send_msg("$output", "f", "The value of master in site table is $masteripinsite, can't get corresponding network interface");
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
probe_utils->send_msg("$output", "d", "Start to capture every message during discovery process......");
|
||||
|
||||
my $varlogmsg = "/var/log/messages";
|
||||
my $clusterlog = "/var/log/xcat/cluster.log";
|
||||
my $computelog = "/var/log/xcat/computes.log";
|
||||
|
||||
my $httplog;
|
||||
my $os = probe_utils->get_os();
|
||||
if ($os eq "redhat") {
|
||||
$httplog = "/var/log/httpd/access_log";
|
||||
} elsif ($os eq "sles") {
|
||||
$httplog = "/var/log/apache2access_log";
|
||||
} elsif ($os eq "ubuntu") {
|
||||
$httplog = "/var/log/apache2/access.log";
|
||||
}
|
||||
|
||||
open(VARLOGMSGFILE, "tail -f $varlogmsg 2>&1 |");
|
||||
open(CLUSTERLOGFILE, "tail -f $clusterlog 2>&1 |");
|
||||
open(HTTPLOGFILE, "tail -f $httplog 2>&1 |");
|
||||
open(COMPUTERFILE, "tail -f $computelog 2>&1 |");
|
||||
|
||||
my $select = new IO::Select;
|
||||
$select->add(\*VARLOGMSGFILE);
|
||||
$select->add(\*CLUSTERLOGFILE);
|
||||
$select->add(\*HTTPLOGFILE);
|
||||
$select->add(\*COMPUTERFILE);
|
||||
$| = 1;
|
||||
|
||||
my $line = "";
|
||||
my @hdls;
|
||||
my $hdl;
|
||||
for (; ;) {
|
||||
if (@hdls = $select->can_read(0)) {
|
||||
foreach $hdl (@hdls) {
|
||||
if ($hdl == \*VARLOGMSGFILE) {
|
||||
chomp($line = <VARLOGMSGFILE>);
|
||||
my @tmp = split(/ /, $line);
|
||||
if ($tmp[4] =~ /dhcpd:/i) {
|
||||
handle_dhcp_msg("$line", $nics);
|
||||
} elsif ($tmp[4] =~ /in.tftpd/i) {
|
||||
handle_tftp_msg("$line");
|
||||
}
|
||||
} elsif ($hdl == \*CLUSTERLOGFILE) {
|
||||
chomp($line = <CLUSTERLOGFILE>);
|
||||
handle_cluster_msg("$line");
|
||||
} elsif ($hdl == \*HTTPLOGFILE) {
|
||||
chomp($line = <HTTPLOGFILE>);
|
||||
handle_http_msg("$line");
|
||||
} elsif ($hdl == \*COMPUTERFILE) {
|
||||
chomp($line = <COMPUTERFILE>);
|
||||
handle_compute_msg("$line");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($terminal || (%monitor_nodes && all_monitor_node_done())) {
|
||||
&dump_history;
|
||||
close(VARLOGMSGFILE);
|
||||
close(CLUSTERLOGFILE);
|
||||
close(HTTPLOGFILE);
|
||||
close(COMPUTERFILE);
|
||||
exit 0;
|
||||
}
|
||||
sleep 0.01;
|
||||
}
|
||||
|
||||
close(VARLOGMSGFILE);
|
||||
close(CLUSTERLOGFILE);
|
||||
close(HTTPLOGFILE);
|
||||
close(COMPUTERFILE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#-------------------------------------
|
||||
# main process
|
||||
#-------------------------------------
|
||||
if (
|
||||
!GetOptions("--help|h|?" => \$help,
|
||||
"t" => \$test,
|
||||
"V" => \$verbose,
|
||||
"s" => \$static))
|
||||
"t" => \$test,
|
||||
"V" => \$verbose,
|
||||
"m" => \$monitor,
|
||||
"p" => \$pre_check,
|
||||
"T=s" => \$discovery_type,
|
||||
"n=s" => \$noderange,
|
||||
"N=s" => \$nics))
|
||||
{
|
||||
probe_utils->send_msg("$output", "f", "Invalid parameter for $program_name");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
@ -253,23 +941,37 @@ if ($help) {
|
||||
}
|
||||
|
||||
if ($test) {
|
||||
probe_utils->send_msg("$output", "o", "Discovery Check.");
|
||||
probe_utils->send_msg("$output", "o", "Do probe for discovery process, including pro-check for required configuration and realtime monitor of discovery process.Before using this command, please install nslookup command ahead.");
|
||||
exit 0;
|
||||
}
|
||||
|
||||
if ($static) {
|
||||
$rst = check_genesis_file("ppc64");
|
||||
if ($rst) {
|
||||
probe_utils->send_msg("$output", "f", "Genesis files for ppc64/ppc64le failed.");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", "Genesis files for ppc64/ppc64le success.");
|
||||
}
|
||||
$rst = check_genesis_file("x86_64");
|
||||
if ($rst) {
|
||||
probe_utils->send_msg("$output", "f", "Genesis files for x86_64 failed.");
|
||||
} else {
|
||||
probe_utils->send_msg("$output", "o", "Genesis files for x86_64 success.");
|
||||
if (defined($noderange) && !defined($discovery_type)) {
|
||||
probe_utils->send_msg("$output", "f", "Option '-n' must used with '-m'");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
|
||||
if (defined($discovery_type)) {
|
||||
unless (@valid_discovery_type ~~ /^$discovery_type$/) {
|
||||
probe_utils->send_msg("$output", "f", "Invalid discovery type. the vaild types are $valid_discovery_type_str");
|
||||
probe_utils->send_msg("$output", "d", "$::USAGE");
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($pre_check) {
|
||||
exit 1 if (do_pre_check($nics));
|
||||
}
|
||||
|
||||
if ($monitor) {
|
||||
$rst = do_monitor();
|
||||
}
|
||||
|
||||
if (!$monitor && !$pre_check) {
|
||||
$rst = do_pre_check();
|
||||
exit 1 if ($rst);
|
||||
|
||||
$rst = do_monitor();
|
||||
}
|
||||
|
||||
exit $rst;
|
||||
|
@ -84,34 +84,54 @@ sub loadsubcmds {
|
||||
sub format_cmd_output {
|
||||
my $line = shift;
|
||||
my $nocolor = shift;
|
||||
|
||||
if ($line =~ /\[(\w+)\]\s*:\s*(.+)/) {
|
||||
my $flag = $1;
|
||||
my $msg = $2;
|
||||
if ($flag =~ /failed/i) {
|
||||
if ($nocolor) {
|
||||
print "[FAIL] ";
|
||||
} else {
|
||||
print BOLD RED "[FAIL] ";
|
||||
my $flag = $1;
|
||||
my $msg = $2;
|
||||
my @tmpmsg = split(" ", $msg);
|
||||
my $maxlen = 80;
|
||||
my @finalmsg = ();
|
||||
my $str = "";
|
||||
foreach my $word (@tmpmsg) {
|
||||
$str .= $word . " ";
|
||||
if (length($str) > $maxlen) {
|
||||
push @finalmsg, $str;
|
||||
$str = "";
|
||||
}
|
||||
}
|
||||
push @finalmsg, $str if ($str ne "");
|
||||
|
||||
for (my $i = 0 ; $i < $#finalmsg + 1 ; $i++) {
|
||||
if ($i ne $#finalmsg) {
|
||||
print "$finalmsg[$i]\n";
|
||||
next;
|
||||
}
|
||||
my $space = " " x ($maxlen - length($finalmsg[$i]) + 5);
|
||||
print "$finalmsg[$i]$space";
|
||||
|
||||
if ($flag =~ /failed/i) {
|
||||
if ($nocolor) {
|
||||
print "[FAIL]\n";
|
||||
} else {
|
||||
print BOLD RED "[FAIL]\n";
|
||||
}
|
||||
} elsif ($flag =~ /warning/i) {
|
||||
if ($nocolor) {
|
||||
print "[WARN]\n";
|
||||
} else {
|
||||
print BOLD BLUE "[WARN]\n";
|
||||
}
|
||||
} elsif ($flag =~ /ok/i) {
|
||||
if ($nocolor) {
|
||||
print "[ OK ]\n";
|
||||
} else {
|
||||
print BOLD GREEN "[ OK ]\n";
|
||||
}
|
||||
} elsif ($flag =~ /debug/i) {
|
||||
print "\n";
|
||||
} elsif ($flag =~ /info/i) {
|
||||
print "[INFO]\n";
|
||||
}
|
||||
} elsif ($flag =~ /warning/i) {
|
||||
if ($nocolor) {
|
||||
print "[WARN] ";
|
||||
} else {
|
||||
print BOLD BLUE "[WARN] ";
|
||||
}
|
||||
} elsif ($flag =~ /ok/i) {
|
||||
if ($nocolor) {
|
||||
print "[ OK ] ";
|
||||
} else {
|
||||
print BOLD GREEN "[ OK ] ";
|
||||
}
|
||||
} elsif ($flag =~ /debug/i) {
|
||||
print " ";
|
||||
} elsif ($flag =~ /info/i) {
|
||||
print "[INFO] ";
|
||||
}
|
||||
print "$msg\n";
|
||||
} else {
|
||||
print "$line\n";
|
||||
}
|
||||
@ -210,10 +230,11 @@ if ($ARGV[0] eq "-l") {
|
||||
}
|
||||
|
||||
if (!defined($pluginname)) {
|
||||
print "There isn't sub command input from command line\n";
|
||||
print "There isn't sub command input from command line, please use '-l' to list all valid subcommand\n";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
|
||||
for (my $i = 0 ; $i < $optnum + 1 ; $i++) {
|
||||
shift @tmpargv;
|
||||
}
|
||||
@ -223,9 +244,29 @@ my $subcmd = "$plugin_dir/$pluginname $pluginattrs";
|
||||
print "\nsubcmd = $subcmd\n" if ($verbose);
|
||||
|
||||
open(PIPE, "$subcmd |");
|
||||
|
||||
my $terminal = 0;
|
||||
my $subcmdpid = 0;
|
||||
my @tmpoutput = `ps axjf |grep -v grep|grep -v ps|grep -v bash|grep $$`;
|
||||
foreach (@tmpoutput) {
|
||||
@psline = split(" ", $_); $subcmdpid = $psline[1] if (($psline[0] eq $$) && ($psline[1] ne $$) && ($psline[2] eq $$));
|
||||
}
|
||||
$SIG{TERM} = $SIG{INT} = sub {
|
||||
$terminal = 1;
|
||||
};
|
||||
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
format_cmd_output($_, $nocolor);
|
||||
if ($terminal && $subcmdpid) {
|
||||
kill 'INT', $subcmdpid;
|
||||
while (<PIPE>) {
|
||||
chomp;
|
||||
format_cmd_output($_, $nocolor);
|
||||
}
|
||||
close(PIPE);
|
||||
exit $?;
|
||||
}
|
||||
}
|
||||
close(PIPE); # This will set the $? properly
|
||||
|
||||
|
Reference in New Issue
Block a user