mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-07-07 21:35:34 +00:00
971 lines
31 KiB
Perl
Executable File
971 lines
31 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# 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_utils;
|
|
use hierarchy;
|
|
use xCAT::ServiceNodeUtils;
|
|
use xCAT::NetworkUtils;
|
|
use File::Basename;
|
|
use File::Copy;
|
|
use Data::Dumper;
|
|
use Getopt::Long qw(:config no_ignore_case);
|
|
|
|
my $help = 0; #command line attribute '-h', get usage information
|
|
my $test = 0; #command line attribute '-T'
|
|
my $hierarchy = 0;
|
|
my $verbose = 0; #command line attribute '-V'
|
|
my $noderange; #command line attribute '-n'
|
|
my $output = "stdout"; #used by probe_utils->send_msg("$output", "o", "xxxxxxxxxx"); print output to STDOUT
|
|
my $rst = 0; #the exit code of current command
|
|
my $terminal = 0; #means get INT signal from STDIN
|
|
my $installnic;
|
|
|
|
#save all output from commands running on SNs and MN
|
|
# one example:
|
|
# $summaryoutput{mn} = @mn_output_history
|
|
# $summaryoutput{SN1} = @SN1_output_history
|
|
my %summaryoutput;
|
|
|
|
my $is_sn;
|
|
$is_sn = 1 if (-e "/etc/xCATSN");
|
|
|
|
|
|
#-------------------------------------
|
|
# Usage
|
|
#-------------------------------------
|
|
my $program_name = basename("$0"); #current sub_command name
|
|
$::USAGE = "Usage:
|
|
$program_name -h
|
|
$program_name -i <install_nic> [-V]
|
|
|
|
Description:
|
|
After xCAT installation, use this command to check if xCAT has been installed correctly and is ready for use.
|
|
For hierarchical cluster, only the provision network on the same network as the management node is supported. If in the different network, ignore the results.
|
|
|
|
Options:
|
|
-h : Get usage information of $program_name
|
|
-V : Output more information for debug
|
|
-i : Required. Specify the network interface name of provision network on management node
|
|
";
|
|
|
|
sub do_main_job {
|
|
my $rst = 0;
|
|
my @error = ();
|
|
my $checkpoint;
|
|
my $rc = 0;
|
|
my $installnicip;
|
|
|
|
#check if all xcat deamons are running
|
|
$checkpoint = "All xCAT deamons are running";
|
|
$rst = check_all_xcat_deamons(\@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
return $rst if ($rst);
|
|
|
|
#check if xcatd can receive request
|
|
$checkpoint = "xcatd can receive command request";
|
|
$rst = check_xcatd_receive_request(\@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
return $rst if ($rst);
|
|
|
|
#check 'site' table configuratiions
|
|
my %sitetable;
|
|
$checkpoint = "'site' table is configured correctly";
|
|
$rst = check_site_table(\%sitetable, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
return $rst if ($rst);
|
|
|
|
#check network configuratiions
|
|
$checkpoint = "Provision network is configured correctly";
|
|
$rst = check_network(\%sitetable, \$installnicip, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
return $rst if ($rst);
|
|
|
|
#check 'passwd' table configuratiions
|
|
$checkpoint = "'passwd' table is configured correctly";
|
|
$rst = check_passwd_table(\@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check important directory
|
|
$checkpoint = "Important directory is configured correctly";
|
|
$rst = check_directory(\%sitetable, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check if SElinux is disabled
|
|
$checkpoint = "SELinux is disabled on current server";
|
|
$rst = check_selinux(\@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check http service
|
|
$checkpoint = "HTTP service works well";
|
|
$rst = check_http_service($installnicip, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check tftp service
|
|
$checkpoint = "TFTP service works well";
|
|
$rst = check_tftp_service($installnicip, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check DNS service
|
|
$checkpoint = "DNS service works well";
|
|
$rst = check_dns_service(\%sitetable, $installnicip, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check DHCP service
|
|
$checkpoint = "DHCP service works well";
|
|
$rst = check_dhcp_service($installnicip, \@error);
|
|
print_check_result($checkpoint, "f", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#Below are the 'warning` level check points
|
|
|
|
#check if firewall is close
|
|
$checkpoint = "Firewall is closed on current server";
|
|
$rst = check_firewall(\@error);
|
|
print_check_result($checkpoint, "w", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check disk space
|
|
$checkpoint = "The disk space is enough for xCAT to work";
|
|
$rst = check_disk(\@error);
|
|
print_check_result($checkpoint, "w", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
|
|
#some sepecific check points in MN
|
|
if (!$is_sn) {
|
|
|
|
#check if server ip is a static ip in MN
|
|
$checkpoint = "The IP of master is a static IP address";
|
|
$rst = check_server_ip_static($installnicip, \@error);
|
|
print_check_result($checkpoint, "w", $rst, \@error);
|
|
$rc |= $rst;
|
|
|
|
#check if dhcpd.leases is less than 100M
|
|
$checkpoint = "The dhcpd.leases file is less than 100M";
|
|
$rst = check_dhcp_leases(\@error);
|
|
print_check_result($checkpoint, "w", $rst, \@error);
|
|
$rc |= $rst;
|
|
}
|
|
|
|
return $rc;
|
|
}
|
|
|
|
sub summary_all_jobs_output {
|
|
my $rst = 0;
|
|
|
|
if ($terminal) {
|
|
return 0;
|
|
}
|
|
|
|
#DO SUMMARY DEPENDING ON YOUR SUB_COMMAND NEED
|
|
probe_utils->send_msg("$output", "d", "======================do summary=====================");
|
|
|
|
#print "summaryoutput:\n";
|
|
#print Dumper \%summaryoutput;
|
|
|
|
my @summary;
|
|
push @summary, "[ok]:[MN]: Check on MN PASS.";
|
|
my $ok_section = 0;
|
|
foreach my $line (@{ $summaryoutput{mn} }) {
|
|
if ($line =~ /(\[failed\]\s*):\s*(.*)/) {
|
|
push @summary, "$1: $2";
|
|
$summary[0] = "[failed]:[MN]: Check on MN FAILED.";
|
|
$ok_section = 0;
|
|
} elsif ($line =~ /(\[warning\]\s*):\s*(.*)/) {
|
|
push @summary, "$1: $2";
|
|
$ok_section = 0;
|
|
} elsif ($line =~ /(\[debug\]\s*):\s*(.*)/ && !$ok_section) {
|
|
push @summary, "$1: $2";
|
|
} elsif ($line =~ /(\[ok\]\s*):\s*(.*)/) {
|
|
$ok_section = 1;
|
|
}
|
|
|
|
}
|
|
|
|
my %summary_sn = ();
|
|
foreach my $node (keys %summaryoutput) {
|
|
next if ($node eq "mn");
|
|
${ $summary_sn{$node}{"rst"} } = 1;
|
|
push @{ $summary_sn{$node}{"details"} }, "[ok]:[SN:$node]: Check on SN $node PASS.";
|
|
$ok_section = 0;
|
|
foreach my $log (@{ $summaryoutput{$node} }) {
|
|
if ($log =~ /(\[failed\]\s*):\s*(.*)/) {
|
|
push @{ $summary_sn{$node}{"details"} }, "$1: $2";
|
|
${ $summary_sn{$node}{"rst"} } = 0;
|
|
$summary_sn{$node}{"details"}[0] = "[failed]:[SN:$node]: Check on SN $node FAILED.";
|
|
$ok_section = 0;
|
|
} elsif ($log =~ /(\[warning\]\s*):\s*(.*)/) {
|
|
push @{ $summary_sn{$node}{"details"} }, "$1: $2";
|
|
$ok_section = 0;
|
|
} elsif ($log =~ /(\[debug\]\s*):\s*(.*)/ && !$ok_section) {
|
|
push @{ $summary_sn{$node}{"details"} }, "$1: $2";
|
|
} elsif ($log =~ /(\[ok\]\s*):\s*(.*)/) {
|
|
$ok_section = 1;
|
|
} elsif ($log !~ /^(\[\w+\]\s*):\s*(.*)/) {
|
|
push @{ $summary_sn{$node}{"details"} }, "[failed]: $log";
|
|
${ $summary_sn{$node}{"rst"} } = 0;
|
|
$summary_sn{$node}{"details"}[0] = "[failed]:[SN:$node]: Check on SN $node FAILED.";
|
|
$ok_section = 0;
|
|
}
|
|
}
|
|
}
|
|
if ($summary[0] =~ /^\[ok\]:/) {
|
|
foreach (@summary) {
|
|
print "$_\n";
|
|
}
|
|
}
|
|
|
|
foreach my $node (keys %summary_sn) {
|
|
if (${ $summary_sn{$node}{"rst"} }) {
|
|
foreach (@{ $summary_sn{$node}{"details"} }) {
|
|
print "$_\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($summary[0] =~ /^\[failed\]:/) {
|
|
foreach (@summary) {
|
|
print "$_\n";
|
|
}
|
|
}
|
|
|
|
foreach my $node (keys %summary_sn) {
|
|
if (!${ $summary_sn{$node}{"rst"} }) {
|
|
foreach (@{ $summary_sn{$node}{"details"} }) {
|
|
print "$_\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub print_check_result {
|
|
my $msg = shift;
|
|
my $error_level = shift;
|
|
my $check_return_code = shift;
|
|
my $error_msg_ref = shift;
|
|
|
|
if ($check_return_code == 1) {
|
|
probe_utils->send_msg("$output", "$error_level", $msg);
|
|
probe_utils->send_msg("$output", "d", "$_") foreach (@$error_msg_ref);
|
|
} elsif ($check_return_code == 2) {
|
|
return;
|
|
} else {
|
|
probe_utils->send_msg("$output", "o", $msg);
|
|
}
|
|
|
|
}
|
|
|
|
sub check_all_xcat_deamons {
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
my @deamon_list = ("SSL listener",
|
|
"DB Access",
|
|
"UDP listener",
|
|
"install monitor",
|
|
"Discovery worker",
|
|
"Command log writer");
|
|
|
|
my $output = `ps aux|grep -v grep|grep xcatd`;
|
|
foreach my $deamon (@deamon_list) {
|
|
if ($output !~ /$deamon/) {
|
|
push @$error_ref, "Deamon '$deamon' isn't running";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_xcatd_receive_request {
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
#check important port
|
|
my @port_list = ("xcatdport", "xcatiport");
|
|
foreach my $port_attr (@port_list) {
|
|
my $port = `lsdef -t site -i $port_attr -c| awk -F'=' '{print \$2}'`;
|
|
chomp($port);
|
|
if ($port) {
|
|
my $cmdoutput = `netstat -ant|grep LISTEN|grep $port`;
|
|
if ($?) {
|
|
push @$error_ref, "Attribute '$port_attr' in site table is set to $port, but xcatd isn't listening on $port";
|
|
$rst = 1;
|
|
}
|
|
} else {
|
|
push @$error_ref, "Attribute '$port_attr' isn't set in 'site' table";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
return $rst if ($rst);
|
|
|
|
#send one command to test if xcatd can receive request
|
|
my $cmdoutput = `lsxcatd -a 2>&1`;
|
|
if ($?) {
|
|
my @lines = split("[\n\r]", $cmdoutput);
|
|
push @$error_ref, $_ foreach (@lines);
|
|
$rst = 1;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_site_table {
|
|
my $sitetable_ref = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
my @attr_list = ("master", "domain", "installdir", "tftpdir");
|
|
foreach my $attr (@attr_list) {
|
|
my $value;
|
|
$value = `lsdef -t site -i $attr -c | awk -F'=' '{print \$2}'`;
|
|
chomp($value);
|
|
if ($value eq "") {
|
|
push @$error_ref, "There isn't '$attr' definition in 'site' table";
|
|
$rst = 1;
|
|
} else {
|
|
if (($attr eq "master") and (!probe_utils->is_ip_addr("$value"))) {
|
|
push @$error_ref, "The value of 'master' in 'site' table isn't an IP addres";
|
|
$rst = 1;
|
|
}
|
|
$sitetable_ref->{$attr} = $value;
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_passwd_table {
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my $passwd = `tabdump passwd |awk -F',' '/system/ { gsub(/"/, "", \$2); gsub(/"/, "", \$3); print \$2,\$3 }'`;
|
|
chomp($passwd);
|
|
my ($username, $pw) = split(" ", $passwd);
|
|
if ($username eq "" || $pw eq "") {
|
|
push @$error_ref, "There isn't username or password for 'system' in 'passwd' table";
|
|
$rst = 1;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_network {
|
|
my $sitetable_ref = shift;
|
|
my $serverip_ref = shift; #output arguments
|
|
my $error_ref = shift; #output arguments
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
if ($is_sn) {
|
|
|
|
# on SN, get ip address by compare 'master' attribute in 'site' table
|
|
# choose the one in the same network with 'master'
|
|
my @ipoutput = `ip addr show | grep inet | grep -v inet6 2>&1`;
|
|
foreach (@ipoutput) {
|
|
if ($_ =~ /inet\s+(.+)\/(.+)\s+brd\s+(.+)\s+scope global/i) {
|
|
if (xCAT::NetworkUtils::isInSameSubnet($sitetable_ref->{master}, $1, $2, 1)) {
|
|
$$serverip_ref = $1;
|
|
}
|
|
}
|
|
}
|
|
if (!defined($$serverip_ref) || ($$serverip_ref eq "")) {
|
|
push @$error_ref, "There isn't IP in current server has the same network as master '$sitetable_ref->{master}'";
|
|
$rst = 1;
|
|
}
|
|
} else { # on MN
|
|
my $nics = `ip addr show $installnic >/dev/null 2>&1`;
|
|
if ($?) {
|
|
push @$error_ref, "There isn't NIC '$installnic' in current server";
|
|
$rst = 1;
|
|
} else {
|
|
$$serverip_ref = `ip addr show $installnic | awk -F" " '/inet / {print \$2}'|awk -F"/" '{print \$1}'`;
|
|
chomp($$serverip_ref);
|
|
if (!defined($$serverip_ref) || ($$serverip_ref eq "")) {
|
|
push @$error_ref, "There isn't IP address assigned to NIC $installnic";
|
|
$rst = 1;
|
|
} else {
|
|
if ($$serverip_ref ne $sitetable_ref->{master}) {
|
|
push @$error_ref, "The IP $$serverip_ref of $installnic doesn't equal the value of 'master' in 'site' table";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
my $networks = `tabdump networks|grep -v "^#"`;
|
|
$networks =~ s/\"//g;
|
|
my $netcnt = `echo "$networks"|wc -l`;
|
|
my $hit = 0;
|
|
for (my $i = 1 ; $i < $netcnt + 1 ; $i++) {
|
|
my $line = `echo "$networks" |sed -n ${i}p |awk -F"," '{print \$2,\$3,\$4}'`;
|
|
chomp($line);
|
|
if ($line =~ /(.+) (.+) (.+)/) {
|
|
if ($is_sn) {
|
|
$hit = 1 if (probe_utils->is_ip_belong_to_net("$1", "$2", $$serverip_ref));
|
|
} else {
|
|
$hit = 1 if (probe_utils->is_ip_belong_to_net("$1", "$2", $$serverip_ref) && ("$3" eq "$installnic"));
|
|
}
|
|
}
|
|
}
|
|
if (!$hit) {
|
|
push @$error_ref, "IP $$serverip_ref of $installnic doesn't belong to any network defined in 'networks' table";
|
|
$rst = 1;
|
|
}
|
|
return $rst;
|
|
}
|
|
|
|
sub check_server_ip_static {
|
|
my $serverip = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
if (!probe_utils->is_static_ip("$serverip", "$installnic")) {
|
|
push @$error_ref, "The value '$serverip' of 'master' in 'site' table isn't a static ip";
|
|
$rst = 1;
|
|
}
|
|
return $rst;
|
|
}
|
|
|
|
|
|
sub check_directory {
|
|
my $sitetable_ref = shift;
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my @dir_list = ("installdir", "tftpdir");
|
|
foreach my $dir (@dir_list) {
|
|
if ($sitetable_ref->{$dir} eq "") {
|
|
push @$error_ref, "There isn't '$dir' definition in 'site' table";
|
|
$rst = 1;
|
|
} else {
|
|
if (!-e "$sitetable_ref->{$dir}") {
|
|
push @$error_ref, "There isn't '$sitetable_ref->{$dir}' directory on current server";
|
|
$rst = 1;
|
|
} else {
|
|
if ($is_sn) {
|
|
my $mountoutput = `mount | grep '$sitetable_ref->{$dir}'`;
|
|
chomp($mountoutput);
|
|
|
|
my $mountip;
|
|
if ($mountoutput =~ /(.+):$sitetable_ref->{$dir} on $sitetable_ref->{$dir} /) {
|
|
my $mountsource = $1;
|
|
if (xCAT::NetworkUtils->isIpaddr($mountsource)) {
|
|
$mountip = $mountsource;
|
|
} else {
|
|
$mountip = xCAT::NetworkUtils->getipaddr($mountsource);
|
|
}
|
|
}
|
|
|
|
if ($mountip ne $sitetable_ref->{master}) {
|
|
push @$error_ref, "$dir '$sitetable_ref->{$dir}' isn't mounted from the management node";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
|
|
sub check_disk {
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my %dir_expectedspace_list = ("/var" => 1, "/tmp" => 1, "/install" => 10);
|
|
my %mountpointinfo;
|
|
foreach my $dir (keys %dir_expectedspace_list) {
|
|
my $output = `df --block-size=1G $dir|tail -n 1`;
|
|
chomp($output);
|
|
my @splitoutput = split(" ", $output);
|
|
$mountpointinfo{ $splitoutput[5] }{available} = $splitoutput[3];
|
|
$mountpointinfo{ $splitoutput[5] }{need} += $dir_expectedspace_list{$dir};
|
|
push @{ $mountpointinfo{ $splitoutput[5] }{mount} }, $dir;
|
|
}
|
|
|
|
my $msg = "";
|
|
foreach $mountpoint (keys %mountpointinfo) {
|
|
if ($mountpointinfo{$mountpoint}{need} > $mountpointinfo{$mountpoint}{available}) {
|
|
foreach (@{ $mountpointinfo{$mountpoint}{mount} }) {
|
|
$msg .= "'$_' needs $dir_expectedspace_list{$_} GiB disk space. ";
|
|
}
|
|
my $mountmun = $#{$mountpointinfo{$mountpoint}{mount}} +1 ;
|
|
if($mountmun >1){
|
|
$msg .= "These directories are parts of file system '$mountpoint'. The free space available in directory '$mountpoint' is $mountpointinfo{$mountpoint}{available} GiB, it is not enough.";
|
|
}else{
|
|
$msg .= "This directory is a part of file system '$mountpoint'. The free space available in directory '$mountpoint' is $mountpointinfo{$mountpoint}{available} GiB, it is not enough.";
|
|
}
|
|
$rst = 1;
|
|
}
|
|
}
|
|
if ($rst) {
|
|
push @$error_ref, "$msg";
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_selinux {
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
if (probe_utils->is_selinux_enable()) {
|
|
push @$error_ref, "SELinux is enabled on current server";
|
|
$rst = 1;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_firewall {
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
if (probe_utils->is_firewall_open()) {
|
|
push @$error_ref, "Firewall is configured on current server";
|
|
$rst = 1;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_http_service {
|
|
my $serverip = shift;
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
`which wget > /dev/null 2>&1`;
|
|
if ($?) {
|
|
push @$error_ref, "HTTP check need 'wget' tool, please install 'wget' tool and try again";
|
|
$rst = 1;
|
|
} else {
|
|
if (!probe_utils->is_http_ready("$serverip")) {
|
|
push @$error_ref, "HTTP service isn't ready on $serverip";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
|
|
sub check_tftp_service {
|
|
my $serverip = shift;
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my $nodename = `hostname -s`;
|
|
chomp($nodename);
|
|
|
|
# For sn, 'setuptftp' attribute could be set to '0' or '1'.
|
|
# if '0', sn does not need to provie TFTP service, will not check it
|
|
my $checktftp = 1;
|
|
if ($is_sn) {
|
|
$checktftp = `lsdef $nodename -i setuptftp -c | awk -F'=' '{print \$2}' `;
|
|
chomp($checktftp);
|
|
}
|
|
if ($checktftp) {
|
|
`which tftp > /dev/null 2>&1`;
|
|
if ($?) {
|
|
push @$error_ref, "TFTP check need 'tftp' tool, please install 'tftp' tool and try again";
|
|
$rst = 1;
|
|
} else {
|
|
$msg = "TFTP service is ready on $serverip";
|
|
if (!probe_utils->is_tftp_ready("$serverip")) {
|
|
push @$error_ref, "TFTP service isn't ready on $serverip";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
} else {
|
|
$rst = 2;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_dns_service {
|
|
my $sitetable_ref = shift;
|
|
my $serverip = shift;
|
|
my $error_ref = shift;
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my $nodename = `hostname -s`;
|
|
chomp($nodename);
|
|
|
|
# For sn, 'setupdns' attribute could be set to '0' or '1'.
|
|
# if '0', sn does not need to provie DNS service, will not check it
|
|
my $checkdns = 1;
|
|
if ($is_sn) {
|
|
$checkdns = `lsdef $nodename -i setupnameserver -c | awk -F'=' '{print \$2}'`;
|
|
chomp($checkdns);
|
|
}
|
|
|
|
if ($checkdns) {
|
|
`which nslookup > /dev/null 2>&1`;
|
|
if ($?) {
|
|
push @$error_ref, "DNS check need 'nslookup' tool, please install 'nslookup' tool and try again";
|
|
$rst = 1;
|
|
} else {
|
|
if ($is_sn) {
|
|
|
|
# on sn, nslookup it's ip to check DNS service
|
|
if (!probe_utils->is_dns_ready("$serverip", "$sitetable_ref->{master}", "$nodename", "$sitetable_ref->{domain}")) {
|
|
push @$error_ref, "DNS service isn't ready on $serverip";
|
|
$rst = 1;
|
|
}
|
|
} else {
|
|
my $rc = 0;
|
|
|
|
# if this is a hierarchical cluster, nslookup one of sn to check DNS service
|
|
my @snlist = xCAT::ServiceNodeUtils->getAllSN();
|
|
my $sntmp = shift(@snlist);
|
|
if ($sntmp) {
|
|
my $sninfo = `cat /etc/hosts | grep $sntmp`;
|
|
if ($sninfo =~ /(\d+).(\d+).(\d+).(\d+)/) {
|
|
my $snip = "$1.$2.$3.$4";
|
|
if (!probe_utils->is_dns_ready("$snip", "$serverip", "$sntmp", "$sitetable_ref->{domain}")) {
|
|
$rc = 1;
|
|
}
|
|
}
|
|
} else {
|
|
|
|
# if there is no sn, nslookup mnip
|
|
my $nslkp = `nslookup $serverip $serverip 2>&1`;
|
|
chomp($nslkp);
|
|
my $tmp = grep { $_ =~ "Server:[\t\s]*$serverip" } split(/\n/, $nslkp);
|
|
if (!$tmp) {
|
|
$rc = 1;
|
|
}
|
|
}
|
|
if ($rc) {
|
|
push @$error_ref, "DNS service isn't ready on $serverip";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
}
|
|
} esle {
|
|
$rst = 2;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
|
|
sub check_dhcp_service {
|
|
my $serverip = shift;
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
|
|
# For sn, 'setupdhcp' attribute could be set to '0' or '1'.
|
|
# if '0', sn does not need to provie DHCP service, will not check it
|
|
if ($is_sn) {
|
|
my $nodename = `hostname -s`;
|
|
chomp($nodename);
|
|
my $checkdhcp = `lsdef $nodename -i setupdhcp -c | awk -F'=' '{print \$2}'`;
|
|
chomp($checkdhcp);
|
|
if ($checkdhcp) {
|
|
|
|
# on sn, just check dhcpd service whether running
|
|
my $dhcpoutput = `ps aux | grep dhcpd |grep -v grep`;
|
|
if (!$dhcpoutput) {
|
|
push @$error_ref, "There isn't 'dhcpd' deamon in current server";
|
|
$rst = 1;
|
|
}
|
|
} else {
|
|
$rst = 2;
|
|
}
|
|
} else {
|
|
my $rc = 0;
|
|
{ #very important brace to create a block
|
|
my @snlist = xCAT::ServiceNodeUtils->getAllSN();
|
|
my $sntmp = shift(@snlist);
|
|
if ($sntmp) {
|
|
my $tmp = `makedhcp -q $sntmp`;
|
|
if ($?) {
|
|
push @$error_ref, "makedhcp -q $sntmp failed";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
last;
|
|
}
|
|
chomp($tmp);
|
|
my $snip = xCAT::NetworkUtils->getipaddr($sntmp);
|
|
my $snmac = `lsdef $sntmp -i mac -c | awk -F'=' '{print \$2}'`;
|
|
chomp($snmac);
|
|
my $tmpmac;
|
|
if ($tmp =~ /$sntmp: ip-address = $snip, hardware-address = (.+)/) {
|
|
$tmpmac = $1;
|
|
if ($tmpmac !~ $snmac) {
|
|
push @$error_ref, "DHCP server reply is wrong";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
}
|
|
} else {
|
|
push @$error_ref, "DHCP server reply is wrong";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
}
|
|
} else {
|
|
|
|
my $tmp = `chdef xcatmntest groups=all ip=$serverip mac=aa:aa:aa:aa:aa:aa`;
|
|
if ($?) {
|
|
push @$error_ref, "Node simulation by 'chdef' has failed";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
last;
|
|
} else {
|
|
push @$error_ref, "Simulate a node xcatmntest<ip=$serverip mac=aa:aa:aa:aa:aa:aa> to do dhcp test" if ($verbose);
|
|
}
|
|
|
|
`cp /etc/hosts /etc/hosts.bak.probe > /dev/null 2>&1`;
|
|
|
|
open HOSTFILE, ">> /etc/hosts";
|
|
print HOSTFILE "$serverip xcatmntest xcatmntest.$domain";
|
|
close HOSTFILE;
|
|
|
|
probe_utils->send_msg($outputtarget, "d", "To do 'makedhcp xcatmntest'") if ($verbose);
|
|
$tmp = `makedhcp xcatmntest 2>&1`;
|
|
if ($?) {
|
|
push @$error_ref, "makedhcp xcatmntest failed";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
`rmdef xcatmntest`;
|
|
last;
|
|
}
|
|
|
|
$tmp = `makedhcp -q xcatmntest`;
|
|
if ($?) {
|
|
push @$error_ref, "makedhcp -q xcatmntest failed";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
`makedhcp -d xcatmntest && rmdef xcatmntest`;
|
|
last;
|
|
}
|
|
chomp($tmp);
|
|
if ($tmp !~ /xcatmntest: ip-address = $serverip, hardware-address = aa:aa:aa:aa:aa:aa/) {
|
|
push @$error_ref, "DHCP server reply is wrong";
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
$rc = 1;
|
|
`makedhcp -d xcatmntest && rmdef xcatmntest`;
|
|
last;
|
|
}
|
|
|
|
push @$error_ref, "Start clearing simulation information for dhcp test" if ($verbose);
|
|
$tmp = `makedhcp -d xcatmntest && rmdef xcatmntest`;
|
|
returncmdoutput($tmp, $error_ref) if ($verbose);
|
|
|
|
unlink "/etc/hosts";
|
|
move("/etc/hosts.bak.probe", "/etc/hosts");
|
|
}
|
|
}
|
|
if ($rc) {
|
|
push @$error_ref, "Run 'makedhcp -n' if it has not been ran before.";
|
|
$rst = 1;
|
|
}
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub check_dhcp_leases {
|
|
my $error_ref = shift;
|
|
|
|
my $rst = 0;
|
|
@$error_ref = ();
|
|
|
|
my $leasefile = "";
|
|
if (-e "/var/lib/dhcpd/dhcpd.leases") {
|
|
$leasefile = "/var/lib/dhcpd/dhcpd.leases";
|
|
} elsif (-e "/var/lib/dhcp/db/dhcpd.leases") {
|
|
$leasefile = "/var/lib/dhcp/db/dhcpd.leases";
|
|
} elsif (-e "/var/lib/dhcp/dhcpd.leases") {
|
|
$leasefile = "/var/lib/dhcp/dhcpd.leases";
|
|
}
|
|
|
|
my @fileinfo = stat("$leasefile");
|
|
if ($fileinfo[7] > 104857600) {
|
|
my $size_m = $fileinfo[7] / 1048576;
|
|
push @$error_ref, "The size of $leasefile is $size_m M, more than 100M";
|
|
$rst = 1;
|
|
}
|
|
|
|
return $rst;
|
|
}
|
|
|
|
sub returncmdoutput {
|
|
my $rst = shift;
|
|
my $error_ref = shift;
|
|
|
|
chomp($rst);
|
|
my @lines = split("[\n\r]", $rst);
|
|
foreach my $line (@lines) {
|
|
push @$error_ref, $line;
|
|
}
|
|
}
|
|
|
|
#-------------------------------------
|
|
# Clean up test environment
|
|
# -------------------------------------
|
|
sub cleanup {
|
|
my $tmptest = `nodels xcatmntest 2>&1`;
|
|
if ($tmptest !~ /Error: Invalid nodes and\/or groups in noderange: xcatmntest/) {
|
|
`makedhcp -d xcatmntest && rmdef xcatmntest > /dev/null 2>&1`;
|
|
}
|
|
if (-e "/etc/hosts.bak.probe") {
|
|
unlink "/etc/hosts";
|
|
move("/etc/hosts.bak.probe", "/etc/hosts");
|
|
}
|
|
}
|
|
|
|
#-------------------------------------
|
|
# main process
|
|
#-------------------------------------
|
|
my @tmpargv = @ARGV;
|
|
if (
|
|
!GetOptions("--help|h" => \$help,
|
|
"T" => \$test,
|
|
"H" => \$hierarchy,
|
|
"V" => \$verbose,
|
|
"i=s" => \$installnic))
|
|
{
|
|
probe_utils->send_msg("$output", "f", "Invalid parameter for $program_name");
|
|
probe_utils->send_msg("$output", "d", "$::USAGE");
|
|
exit 1;
|
|
}
|
|
|
|
if ($help) {
|
|
if ($output ne "stdout") {
|
|
probe_utils->send_msg("$output", "d", "$::USAGE");
|
|
} else {
|
|
print "$::USAGE";
|
|
}
|
|
exit 0;
|
|
}
|
|
|
|
if ($test) {
|
|
probe_utils->send_msg("$output", "o", "After xcat installation, use this command to check if xcat has been installed correctly and is ready for use. Before using this command, install 'tftp', 'nslookup' and 'wget' commands. Supported platforms are RedHat, SLES and Ubuntu.");
|
|
exit 0;
|
|
}
|
|
|
|
if (!$installnic){
|
|
probe_utils->send_msg("$output", "f", "Option '-i' is required");
|
|
probe_utils->send_msg("$output", "d", "$::USAGE");
|
|
exit 1;
|
|
}
|
|
|
|
#Handle the interrupt signal from STDIN
|
|
$SIG{TERM} = $SIG{INT} = sub {
|
|
$terminal = 1;
|
|
cleanup();
|
|
};
|
|
|
|
#if it is called by hierarchy template, just run job, not to do dispatch
|
|
if ($hierarchy || $is_sn) {
|
|
$rst = do_main_job();
|
|
exit $rst;
|
|
}
|
|
|
|
my @error;
|
|
my $hierarchy_instance = hierarchy->new();
|
|
$rst = $hierarchy_instance->dispatch_cmd($noderange, \@tmpargv, \@error);
|
|
if ($rst) {
|
|
probe_utils->send_msg("$output", "f", "Calculate dispatch command failed");
|
|
foreach (@error) {
|
|
probe_utils->send_msg("$output", "", "$_");
|
|
}
|
|
if ($hierarchy_instance->destory(\@error)) {
|
|
probe_utils->send_msg("$output", "", "$_") foreach (@error);
|
|
}
|
|
exit $rst;
|
|
}
|
|
|
|
my %reply_cache;
|
|
while ($hierarchy_instance->read_reply(\%reply_cache)) {
|
|
foreach my $servers (keys %reply_cache) { #Dispatch_cmd may use SN range to dispatch cms to SNs at one time
|
|
my @server_array = split(",", $servers);
|
|
foreach my $server (@server_array) {
|
|
foreach (@{ $reply_cache{$servers} }) {
|
|
my $msg = "";
|
|
my $logmsg = "";
|
|
|
|
#For cases like below:
|
|
#c910f02c04p04: [ok] :All xCAT deamons are running
|
|
if ($reply_cache{$servers}->[$_] =~ /^(\w+)\s*:\s*(\[\w+\]\s*):\s*(.*)/) {
|
|
if ("$1" eq "$server") {
|
|
$logmsg = "$2: $3";
|
|
$msg = "$2:<$server>: $3";
|
|
}
|
|
|
|
#For cases like below:
|
|
#c910f02c04p05: IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
|
|
} elsif ($reply_cache{$servers}->[$_] =~ /^(\w+)\s*:\s*(.*)/) {
|
|
if ("$1" eq "$server") {
|
|
$logmsg = "$2";
|
|
$msg = "<$server>: $2";
|
|
}
|
|
|
|
#For cases like below:
|
|
#Unable to open socket connection to xcatd daemon on localhost:3001.
|
|
} else {
|
|
if (length($reply_cache{$servers}->[$_])) {
|
|
$logmsg = $reply_cache{$servers}->[$_];
|
|
$msg = "[failed] :[$server]: $reply_cache{$servers}->[$_]";
|
|
}
|
|
}
|
|
probe_utils->send_msg("$output", "", "$msg") if (length($msg));
|
|
push @{ $summaryoutput{$server} }, $logmsg if (length($logmsg));
|
|
}
|
|
}
|
|
}
|
|
if ($terminal) {
|
|
last;
|
|
}
|
|
}
|
|
|
|
if ($hierarchy_instance->destory(\@error)) {
|
|
probe_utils->send_msg("$output", "", "$_") foreach (@error);
|
|
}
|
|
|
|
#-------------------------------------
|
|
# summary all jobs output to display
|
|
#-------------------------------------
|
|
$rst = summary_all_jobs_output();
|
|
|
|
exit $rst;
|
|
|
|
|
|
|
|
|
|
|
|
|