diff --git a/xCAT-probe/lib/perl/ProbeUtils.pm b/xCAT-probe/lib/perl/ProbeUtils.pm new file mode 100644 index 000000000..8304fb76b --- /dev/null +++ b/xCAT-probe/lib/perl/ProbeUtils.pm @@ -0,0 +1,317 @@ +package ProbeUtils; +use strict; +use File::Path; +use File::Copy; + +#----------------------------------------- +=head3 + Description: + Format output message depending on probe framework requirement + Format is [] : + The valid are debug, warning, failed and ok + Attribute: list by input sequence + output: where should output the message + num: the number of + 0: debug + 1: warning + 2: failed + 3: ok + msg: the information need to output + Return value: + 1 : Failed + 0 : success +=cut +#---------------------------------------- +sub send_msg { + my $output=shift; + $output=shift if(($output) && ($output =~ /ProbeUtils/)); + my $num = shift; + my $msg = shift; + my $flag; + + if ($num == 0) { + $flag = "[debug] :"; + }elsif($num == 1) { + $flag = "[warning]:"; + }elsif($num == 2) { + $flag = "[failed] :"; + }elsif($num == 3){ + $flag = "[ok] :"; + } + if($output eq "stdout"){ + print "$flag $msg\n"; + }else{ + if (!open (LOGFILE, ">> $output") ) { + return 1; + } + print LOGFILE "$flag $msg\n"; + close LOGFILE; + } + return 0; +} + +#------------------------------------------ +=head3 + Description: + Judge if a string is a IP address + Attribute: list by input sequence + addr: the string want to be judged + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isIpAddr{ + my $addr = shift; + $addr=shift if(($addr) && ($addr =~ /ProbeUtils/)); + return 0 unless($addr); + return 0 if($addr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + return 0 if ($1 > 255 || $1 == 0 || $2 > 255 || $3 > 255 || $4 > 255); + return 1; +} + +#------------------------------------------ +=head3 + Description: + Judge if a IP address belongs to a network + Attribute: list by input sequence + net : network address, such like 10.10.10.0 + mask: network mask. suck like 255.255.255.0 + ip: a ip address + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isIpBelongToNet{ + my $net=shift; + $net=shift if(($net) && ($net =~ /ProbeUtils/)); + my $mask=shift; + my $targetip=shift; + + return 0 if($net !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + return 0 if($mask !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + return 0 if(! isIpAddr($targetip)); + + 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($targetip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + + my $tmp_net = $bin_mask&$bin_ip; + + my $bin_net=0; + $bin_net=(($1+0)<<24)+(($2+0)<<16)+(($3+0)<<8)+($4+0) if($net =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/); + + return 0 if( $tmp_net != $bin_net); + return 1; +} + +#------------------------------------------ +=head3 + Description: + Get distro name of current operating system + Attribute: list by input sequence + None + Return value: + A string, include value are sles, redhat and ubuntu +=cut +#------------------------------------------ +sub getOS{ + my $os="unknown"; + my $output = `cat /etc/*release* 2>&1`; + if($output =~ /suse/i){ + $os="sles"; + }elsif($output =~ /Red Hat/i){ + $os="redhat"; + }elsif($output =~ /ubuntu/i){ + $os="ubuntu"; + } + + return $os; +} + +#------------------------------------------ +=head3 + Description: + Judge if a IP address is a static IP address + Attribute: list by input sequence + ip: a ip address + nic: the network adapter which ip belongs to + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isStaticIp{ + my $ip=shift; + $ip=shift if(($ip) && ($ip =~ /ProbeUtils/)); + my $nic=shift; + my $os = getOS(); + my $rst=0; + + if($os =~ /redhat/){ + my $output1=`cat /etc/sysconfig/network-scripts/ifcfg-$nic 2>&1 |grep -i IPADDR`; + my $output2=`cat /etc/sysconfig/network-scripts/ifcfg-$nic 2>&1 |grep -i BOOTPROTO`; + $rst=1 if(($output1 =~ /$ip/) && ($output2 =~ /static/i)); + }elsif($os =~ /sles/){ + my $output1=`cat /etc/sysconfig/network/ifcfg-$nic 2>&1 |grep -i IPADDR`; + my $output2=`cat /etc/sysconfig/network/ifcfg-$nic 2>&1 |grep -i BOOTPROTO`; + $rst=1 if(($output1 =~ /$ip/) && ($output2 =~ /static/i)); + }elsif($os =~/ubuntu/){ + my $output=`cat /etc/network/interfaces 2>&1|grep -E "iface\s+$nic"`; + $rst=1 if($output =~ /static/i); + } + return $rst; +} + +#------------------------------------------ +=head3 + Description: + Judge if SELinux is opened in current operating system + Attribute: list by input sequence + None + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isSelinuxEnable{ + if (-e "/usr/sbin/selinuxenabled") { + `/usr/sbin/selinuxenabled`; + if ($? == 0) { + return 1; + } else { + return 0; + } + } else { + return 0; + } +} + +#------------------------------------------ +=head3 + Description: + Judge if firewall is opened in current operating system + Attribute: list by input sequence + None + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isFirewallOpen{ + my $os =getOS(); + my $output; + my $rst=0; + + if($os =~ /redhat/){ + $output=`service iptables status 2>&1`; + $rst=1 if($output =~ /running/i); + }elsif($os =~ /sles/){ + $output=`service SuSEfirewall2_setup status`; + $rst=1 if($output =~ /running/i); + }elsif($os =~/ubuntu/){ + $output=`ufw status`; + $rst=1 if($output =~ /Status: active/i); + } + return $rst; +} + +#------------------------------------------ +=head3 + Description: + Judge if http service is ready to use in current operating system + Attribute: list by input sequence + ip: http server's ip + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isHttpReady{ + my $mnip=shift; + $mnip=shift if(($mnip) && ($mnip =~ /ProbeUtils/)); + + my $http = "http://$mnip/install/postscripts/efibootmgr"; + rename("./efibootmgr", "./efibootmgr.org") if(-e "./efibootmgr"); + + my $outputtmp = `wget $http 2>&1`; + my $rst =$?; + if(($outputtmp =~ /200 OK/) && (!$rst) && (-e "./efibootmgr")){ + unlink("./efibootmgr"); + rename("./efibootmgr.org", "./efibootmgr") if(-e "./efibootmgr.org"); + return 1; + }else{ + rename("./efibootmgr.org", "./efibootmgr") if(-e "./efibootmgr.org"); + return 0; + } +} + +#------------------------------------------ +=head3 + Description: + Judge if tftp service is ready to use in current operating system + Attribute: list by input sequence + ip: tftp server's ip + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isTftpReady{ + my $mnip=shift; + $mnip=shift if(($mnip) && ($mnip =~ /ProbeUtils/)); + + rename("/tftpboot/tftptestt.tmp", "/tftpboot/tftptestt.tmp.old") if(-e "/tftpboot/tftptestt.tmp"); + rename("./tftptestt.tmp", "./tftptestt.tmp.old") if(-e "./tftptestt.tmp"); + + system("touch /tftpboot/tftptestt.tmp"); + my $output = `tftp -4 -v $mnip -c get tftptestt.tmp`; + if((!$?) && (-e "./tftptestt.tmp")){ + unlink("./tftptestt.tmp"); + rename("./tftptestt.tmp.old", "./tftptestt.tmp") if(-e "./tftptestt.tmp.old"); + rename("/tftpboot/tftptestt.tmp.old","/tftpboot/tftptestt.tmp") if(-e "/tftpboot/tftptestt.tmp.old"); + return 1; + }else{ + rename("./tftptestt.tmp.old", "./tftptestt.tmp") if(-e "./tftptestt.tmp.old"); + rename("/tftpboot/tftptestt.tmp.old","/tftpboot/tftptestt.tmp") if(-e "/tftpboot/tftptestt.tmp.old"); + return 0; + } +} + + +#------------------------------------------ +=head3 + Description: + Judge if DNS service is ready to use in current operating system + Attribute: list by input sequence + ip: DNS server's ip + Return value: + 1 : yes + 0 : no +=cut +#------------------------------------------ +sub isDnsReady{ + my $mnip=shift; + $mnip=shift if(($mnip) && ($mnip =~ /ProbeUtils/)); + my $hostname=shift; + my $domain=shift; + + my $output = `nslookup $mnip $mnip 2>&1`; + + if($?){ + return 0; + }else{ + chomp($output); + my $tmp=`echo "$output" |grep "Server:[\t\s]*$mnip" >/dev/null 2>&1`; + print "$tmp"; + return 0 if($?); + $tmp = `echo "$output"|grep "name ="|grep "$hostname\.$domain" >/dev/null 2>&1`; + return 0 if($?); + return 1; + } +} + +1; diff --git a/xCAT-probe/subcmds/xcatmn b/xCAT-probe/subcmds/xcatmn new file mode 100755 index 000000000..7e9c3c21c --- /dev/null +++ b/xCAT-probe/subcmds/xcatmn @@ -0,0 +1,475 @@ +#! /usr/bin/perl + +#use lib "/home/probe/lib/perl"; +use lib "/opt/xcat/probe/lib/perl"; +use ProbeUtils; +use File::Basename; +use Getopt::Long; + +my $proname=basename("$0"); +my $help; +my $mnip; +my $test; +my $output="stdout"; +my $verbose=0; +my $rst=0; + +$::USAGE = "Usage: + $proname -h + $proname -t + $proname [-m] [-f] [-v] + +Description: + After xcat installation, use this command to check if xcat has been installed correctly and is ready for use. + +Options: + -h : get usage information of $proname + -t : to verify if $proname can work, reserve option for probe framework + -m : specify current MN's IP address, if not specified, use master ip in site table + -f : specify where should $proname pass its output to. if not specified, pass output to STDOUT by default. + -v : output more information for debug +"; + +sub returncmdoutput{ + my $rst=shift; + chomp($rst); + my @lines=split("[\n\r]", $rst); + foreach my $line (@lines){ + ProbeUtils->send_msg("$output",0, "$line"); + } +} + + +#------------------------------------- +# main process +#------------------------------------- +if ( + !GetOptions("--help|h|?" => \$help, + "t"=> \$test, + "v"=> \$verbose, + "f=s" => \$output, + "m=s" => \$mnip)) +{ + ProbeUtils->send_msg("$output",2, "Invalid parameter for $proname"); + ProbeUtils->send_msg("$output",0, "$::USAGE"); + exit 1; +} + +if($help){ + if($output ne "stdout"){ + ProbeUtils->send_msg("$output",0, "$::USAGE"); + }else{ + print "$::USAGE"; + } + exit 0; +} + +if($test){ + ProbeUtils->send_msg("$output",3,"After xcat installation, use this command to check if xcat has been installed correctly and is ready for use. Before using this command , please install tftp, nslookup and wget commands ahead. The platform supported are redhat, sles and ubuntu."); + exit 0; +} + +my $hostname=`hostname -s`; +chomp($hostname); +my $hostipaddr=`hostname -i`; +chomp($hostipaddr); +my $othername=`hostname -a`; +chomp($othername); + +ProbeUtils->send_msg("$output",0,"Short hostname of this server is $hostname") if($verbose); +ProbeUtils->send_msg("$output",0,"The address of hostname $hostname is $hostipaddr") if($verbose); +ProbeUtils->send_msg("$output",0,"The other names of $hostname is $othername") if($verbose && ($othername ne "")); + +my $msg="Sub process 'xcatd: SSL listener' is running"; +my $xcatdproc = `ps aux|grep -v grep|grep xcatd`; +chomp($xcatdproc); +if($xcatdproc =~ /xcatd: SSL listener/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="Sub process 'xcatd: DB Access' is running"; +if($xcatdproc =~ /xcatd: DB Access/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="Sub process 'xcatd: UDP listener' is running"; +if($xcatdproc =~ /xcatd: UDP listener/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="Sub process 'xcatd: install monitor' is running"; +if($xcatdproc =~ /xcatd: install monitor/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="Sub process 'xcatd: Discovery worker' is running"; +if($xcatdproc =~ /xcatd: Discovery worker/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="Sub process 'xcatd: Command log writer' is running"; +if($xcatdproc =~ /xcatd: Command log writer/){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",1,"Sub process 'xcatd: Command log writer' isn't running"); +} +exit 1 if($rst); + + +my $xcatdport=`tabdump site 2>&1 | awk -F',' '/xcatdport/ { gsub(/"/, "", \$2) ; print \$2 }'`; +chomp($xcatdport); +ProbeUtils->send_msg("$output",0,"The port used by the xcatd daemon for client/server communication is $xcatdport") if($verbose); +$msg="xcatd is listening on port $xcatdport"; +my $cmdoutput = `netstat -ant|grep LISTEN|grep $xcatdport`; +if($?){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} + +my $xcatiport=`tabdump site 2>&1| awk -F',' '/xcatiport/ { gsub(/"/, "", \$2) ; print \$2 }'`; +chomp($xcatiport); +ProbeUtils->send_msg("$output",0,"The port used by xcatd to receive install status updates from nodes is $xcatiport") if($verbose); +$msg="xcatd is listening on port $xcatiport"; +$cmdoutput = `netstat -ant|grep LISTEN|grep $xcatiport`; +if($?){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} +exit 1 if($rst); + +$msg ="'lsxcatd -a' works"; +$cmdoutput=`lsxcatd -a 2>&1`; +$rst=$?; +returncmdoutput($cmdoutput) if($verbose); +if($rst){ + ProbeUtils->send_msg("$output",2,"$msg"); + exit $rst; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} + +my $masteripinsite=`tabdump site | awk -F',' '/master/ { gsub(/"/, "", \$2) ; print \$2 }'`; +chomp($masteripinsite); +ProbeUtils->send_msg("$output",0, "The value of 'master' in 'site' table is $masteripinsite") if($verbose); +ProbeUtils->send_msg("$output",2, "There isn't 'master' definition in 'site' talbe") if($masteripinsite eq ""); + +$msg="The value of 'master' in 'site' table is a IP address"; +if(ProbeUtils->isIpAddr("$masteripinsite")){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + exit 1; +} + +if($mnip){ + $msg="The IP passed by command line equals the value of 'master' in 'site' table"; + if($mnip eq $masteripinsite){ + ProbeUtils->send_msg("$output",3,"$msg"); + }else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; + } +}else{ + ProbeUtils->send_msg("$output",0,"Use the value of 'master' of 'site' table as MNIP") if($verbose); + $mnip=$masteripinsite; +} + +ProbeUtils->send_msg("$output",0,"MNIP used in below checking is $mnip") if($verbose); + +$msg="There is configuration in 'passwd' table for 'system' for node provision"; +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 ""){ + ProbeUtils->send_msg("$output",0,"There isn't username or password for 'system' in 'passwd' table"); + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} + +$msg="There is a network adapter on current server is configured by IP $mnip"; +my $nic=`ip addr show |grep -B2 $mnip|grep mtu|awk '{print \$2}'|sed -e 's/:\$//'`; +chomp($nic); +if("$nic" eq ""){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",0,"IP $mnip belongs to network adapter $nic") if($verbose); + ProbeUtils->send_msg("$output",3,"$msg"); +} + +$msg="IP $mnip is a static IP on current server"; +if(ProbeUtils->isStaticIp("$mnip", "$nic")){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",1,"IP $mnip is not a static ip on current server"); +} + +$msg="$mnip belongs to one of networks defined in 'networks' table"; +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 =~ /(.+) (.+) (.+)/){ + $hit=1 if(ProbeUtils->isIpBelongToNet("$1", "$2", $mnip) && ("$3" eq "$nic")); + } +} +if($hit){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="There is domain definition in 'site' table"; +my $domain=`tabdump site | awk -F',' '/domain/ { gsub(/"/, "", \$2) ; print \$2 }'`; +chomp($domain); +if($domain){ + ProbeUtils->send_msg("$output",0,"The value of 'domain' in 'site' table is $domain") if($verbose); + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="There are /install and /install/postscripts directory on current server"; +if(-e "/install/postscripts/"){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +$msg="There is /tftpboot directory on current server"; +if(-e "/tftpboot/"){ + ProbeUtils->send_msg("$output",3,"$msg"); +}else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +} + +my $expected=10; +$msg="The free space of / directory is more than $expected G"; +my $diskspace=`df -h|awk '{print \$4,\$6}'|grep -E "/\$"`; +if($?){ + ProbeUtils->send_msg("$output",0,"There isn't any filesystem mount on / directory"); + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + chomp($diskspace); + my ($size, $dir) = split(" ", $diskspace); + $size=~s/G//g; + ProbeUtils->send_msg("$output",0,"The free space of / is $size G") if($verbose); + if($size<$expected){ + ProbeUtils->send_msg("$output",1,"The free space of / is less than $expected G"); + }else{ + ProbeUtils->send_msg("$output",3,"$msg"); + } +} + +$expected=1; +$msg="The free space of /var directory is more than $expected G"; +$diskspace=`df -h|awk '{print \$4,\$6}'|grep -E "/var\$"`; +if(!$?){ + chomp($diskspace); + my ($size, $dir) = split(" ", $diskspace); + $size=~s/G//g; + ProbeUtils->send_msg("$output",0,"The free space of /var is $size G") if($verbose); + if($size<$expected){ + ProbeUtils->send_msg("$output",1,"The free space of /var is less than $expected G"); + }else{ + ProbeUtils->send_msg("$output",3,"$msg"); + } +} + +$expected=1; +$msg="The free space of /tmp directory is more than $expected G"; +$diskspace=`df -h|awk '{print \$4,\$6}'|grep -E "/tmp\$"`; +if(!$?){ + chomp($diskspace); + my ($size, $dir) = split(" ", $diskspace); + $size=~s/G//g; + ProbeUtils->send_msg("$output",0,"The free space of /tmp is $size G") if($verbose); + if($size<$expected){ + ProbeUtils->send_msg("$output",1,"The free space of /tmp is less than $expected G"); + }else{ + ProbeUtils->send_msg("$output",3,"$msg"); + } +} + + +$expected=10; +$msg="The free space of /install directory is more than $expected G"; +$diskspace=`df -h|awk '{print \$4,\$6}'|grep -E "/install\$"`; +if(!$?){ + chomp($diskspace); + my ($size, $dir) = split(" ", $diskspace); + $size=~s/G//g; + ProbeUtils->send_msg("$output",0,"The free space of /install is $size G") if($verbose); + if($size<$expected){ + ProbeUtils->send_msg("$output",1,"The free space of /install is less than $expected G"); + }else{ + ProbeUtils->send_msg("$output",3,"$msg"); + } +} + +$msg="SELinux is disabled on current server"; +if(ProbeUtils->isSelinuxEnable()){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} + +$msg="Firewall is closed on current server"; +if(ProbeUtils->isFirewallOpen()){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} + +`which wget > /dev/null 2>&1`; +if($?){ + ProbeUtils->send_msg("$output",1,"wget command isn't installed on current server, skip checking HTTP service"); +}else{ + $msg="HTTP service is ready on $mnip"; + if(ProbeUtils->isHttpReady("$mnip")){ + ProbeUtils->send_msg("$output",3,"$msg"); + }else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; + } +} + +`which tftp > /dev/null 2>&1`; +if($?){ + ProbeUtils->send_msg("$output",1,"tftp command isn't installed in current server, skip checking tftp service"); +}else{ + $msg="TFTP service is ready on $mnip"; + if(ProbeUtils->isTftpReady("$mnip")){ + ProbeUtils->send_msg("$output",3,"$msg"); + }else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst =1; + } +} + +`which nslookup > /dev/null 2>&1`; +if($?){ + ProbeUtils->send_msg("$output",1,"nslookup command isn't installed in current server, skip checking DNS service"); +}else{ + $msg="DNS server is ready on $mnip"; + ProbeUtils->send_msg("$output",0,"hostname used to check DNS is $hostname, domain used to check DNS is $domain") if($verbose); + if(ProbeUtils->isDnsReady("$mnip","$hostname", "$domain")){ + ProbeUtils->send_msg("$output",3,"$msg"); + }else{ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst =1; + } +} + +my $os=ProbeUtils->getOS(); +my $leasefile=""; +$leasefile="/var/lib/dhcpd/dhcpd.leases" if($os =~ /redhat/i); +$leasefile="/var/lib/dhcp/db/dhcpd.leases" if($os =~ /sles/i); +$leasefile="/var/lib/dhcp/dhcpd.leases" if($os =~ /ubuntu/i); +$msg="The size of $leasefile is less than 100M"; +my $filesizetmp=`du -sb $leasefile`; +if($?){ + returncmdoutput($filesizetmp) if($verbose); + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + chomp($filesizetmp); + my ($size, $file) = split(" ", $filesizetmp); + ProbeUtils->send_msg("$output",0,"The size of $leasefile is $size bytes") if($verbose); + if($size > 104857600){ + ProbeUtils->send_msg("$output",1,"The size of $leasefile is more than 100M"); + }else{ + ProbeUtils->send_msg("$output",3,"$msg"); + } +} + +my $msg="DHCP service is ready on $mnip"; +my $rc=0; +{ #very important brace to create a block + my $tmp=`chdef xcatmntest groups=all ip=$mnip mac=aa:aa:aa:aa:aa:aa`; + if($?){ + returncmdoutput($tmp) if($verbose); + ProbeUtils->send_msg("$output",0,"Simulate a node by chdef failed") if($verbose); + $rc=1; + last; + }else{ + ProbeUtils->send_msg("$output",0,"Simulate a node xcatmntest to do dhcp test") if($verbose); + } + + $tmp=`makehosts xcatmntest`; + if($?){ + returncmdoutput($tmp) if($verbose); + ProbeUtils->send_msg("$output",0,"makehosts xcatmntest failed") if($verbose); + $rc=1; + `rmdef xcatmntest`; + last; + } + + $tmp = `makedhcp xcatmntest 2>&1`; + if($?){ + returncmdoutput($tmp) if($verbose); + ProbeUtils->send_msg("$output",0,"makedhcp xcatmntest failed") if($verbose); + $rc=1; + `makehosts -d xcatmntest && rmdef xcatmntest`; + last; + } + + $tmp = `makedhcp -q xcatmntest`; + if($?){ + returncmdoutput($tmp) if($verbose); + ProbeUtils->send_msg("$output",0,"makedhcp -q xcatmntest failed") if($verbose); + $rc=1; + `makedhcp -d xcatmntest && makehosts -d xcatmntest && rmdef xcatmntest`; + last; + } + chomp($tmp); + if($tmp !~ /xcatmntest: ip-address = $mnip, hardware-address = aa:aa:aa:aa:aa:aa/){ + returncmdoutput($tmp) if($verbose); + ProbeUtils->send_msg("$output",0,"DHCP server's reply is wrong") if($verbose); + $rc=1; + `makedhcp -d xcatmntest && makehosts -d xcatmntest && rmdef xcatmntest`; + last; + } + + ProbeUtils->send_msg("$output",0,"Start to clear simulate information for dhcp test") if($verbose); + $tmp=`makedhcp -d xcatmntest && makehosts -d xcatmntest && rmdef xcatmntest`; + returncmdoutput($tmp) if($verbose); +} +if($rc){ + ProbeUtils->send_msg("$output",2,"$msg"); + $rst=1; +}else{ + ProbeUtils->send_msg("$output",3,"$msg"); +} +exit $rst ; diff --git a/xCAT-probe/xcatprobe b/xCAT-probe/xcatprobe new file mode 100755 index 000000000..1e602b35f --- /dev/null +++ b/xCAT-probe/xcatprobe @@ -0,0 +1,258 @@ +#!/usr/bin/env perl + +use File::Basename; +use Data::Dumper; +use File::Path; +use POSIX qw(WNOHANG setsid :errno_h); +use Term::ANSIColor qw(:constants); +$Term::ANSIColor::AUTORESET=1; + +my $pro_name=basename($0); +my $pro_dir=dirname($0); +#my $plugin_dir="$pro_dir/subcmds"; +my $plugin_dir="/opt/xcat/probe/subcmds"; +my %cmds=(); + +my $verbose=0; +my $nocolor=0; +my $help=0; +my $list=0; + +$::USAGE = "Usage: +xcatprobe -h +xcatprobe -l +xcatprobe -v +xcatprobe [-n] + +Options: + -h : get usage information of $pro_name + -l : list all valid sub commands + -v : print verbose information of $pro_name + -n : print output without colors +"; + +#----------------------------------- +=head3 + Description: + Load sub commands from ~/subcmds directory + Using -t option of command to judge if it is valid. + If command in ~/subcmds has syntax error, or doesn't follow interface specification, this command will be skipped +=cut +#----------------------------------- +sub loadsubcmds{ + my @candidate=glob("$plugin_dir/*"); + my @subcmds=(); + my @validflag=("debug", "warning", "failed", "ok"); + my $output; + + print "Starting to load sub command form ~/subcmds.............\n" if($verbose); + + foreach (@candidate) { + my $cmdname = basename("$_"); + $output = `$_ -t 2>&1`; + chomp($output); + + print "\n-->$_\n[OUTPUT]:\n$output\n" if($verbose); + if($output !~ /\[(\w+)\]\s*:\s*(.+)/){ + print "skip $_ for doing '$_ -t' failed, bad format\n" if($verbose); + next; + }else{ + my $desc =$2; + unless(@validflag ~~ /$1/){ + print "skip $_ for doing '$_ -t' failed, invalid flag\n" if($verbose); + next; + } + $cmds{$cmdname} = $desc; + print "load $_ \n" if($verbose); + } + } + print "\nLoad sub command.........[done]\n" if($verbose); +} + + +#----------------------------------- +=head3 + Description: + Format the output of sub command, make them colorfully. +=cut +#---------------------------------- +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] "; + } + }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 " "; + } + print "$msg\n"; + }else{ + print "$line\n"; + } + return 0; +} + +#----------------------------------- +=head3 + Description: + List all valid sub command in ~/subcmds directory +=cut +#---------------------------------- +sub listvalidsubcmd{ + my $maxlen=0; + foreach my $key (keys %cmds) { + $maxlen=length($key) if(length($key)>$maxlen); + } + $maxlen+=4; + print "Supported sub commands are:\n"; + foreach my $key (keys %cmds){ + my @desc=split(" ", $cmds{$key}); + my $str=""; + my @formatdesc=(); + foreach my $word (@desc){ + $str.=$word." "; + if(length($str)>100){ + push @formatdesc, $str; + $str=""; + } + } + push @formatdesc, $str; + if($nocolor){ + print "$key"; + }else{ + print BOLD GREEN "$key"; + } + my $space=" " x ($maxlen-length($key)); + print "$space $formatdesc[0]\n"; + delete $formatdesc[0]; + $space=" " x $maxlen; + foreach my $line (@formatdesc){ + print "$space $line\n" if(length($line)); + } + + } +} + +####################################### +# main +####################################### +my @tmpargv=@ARGV; +my @supportopt=("-v","-h","-l","-n"); +my $pluginname; +my $optnum=0; +foreach my $attr (@tmpargv){ + if($attr =~ /^-/){ + unless(@supportopt ~~ /$attr/){ + print "Unsupported attribute: $attr\n"; + print $::USAGE; + exit 1; + } + $optnum++; + $help=1 if($attr eq "-h"); + $verbose=1 if($attr eq "-v"); + $list=1 if($attr eq "-l"); + $nocolor=1 if($attr eq "-n"); + }else{ + $pluginname=$attr; + last; + } +} + +&loadsubcmds; +if(defined ($pluginname)){ + my $hit=0; + foreach my $key (keys %cmds){ + $hit=1 if($pluginname eq $key); + } + unless($hit){ + print "Unsupported sub command: $pluginname\n"; + &listvalidsubcmd; + exit 1; + } +} + +if($help){ + print $::USAGE; + exit 0; +} + +if($ARGV[0] eq "-l"){ + &listvalidsubcmd; + exit 0; +} + +if(!defined ($pluginname)){ + print "There isn't sub command input from command line\n"; + exit 0; +} + +for(my $i =0; $i<$optnum+1; $i++){ + shift @tmpargv; +} +my $pluginattrs = join(" ", @tmpargv); + +my $date = `date +"%Y%m%d%H%M%S"`; +chomp($date); +my $cmmpath="/tmp/probe"; +my $cmmfile="$cmmpath/$pluginname.$date"; +mkpath("$cmmpath") unless(-d "$cmmpath"); +`touch $cmmfile`; +my $subcmd="$plugin_dir/$pluginname -f $cmmfile $pluginattrs"; + +print "\n[main] subcmd = $subcmd\n" if($verbose); + +my $subproc = fork(); +my $subrst=0; +if(!defined($subproc)){ + print "Unable to fork new process to run subcommand\n"; + exit 1; +}elsif($subproc==0){ + $SIG{INT} = sub { + print "Sub proc $$ recrive INT signal to exit"; + exit 0; + }; + print "[sub $$] run $subcmd\n----------------------\n" if($verbose); + `$subcmd`; + exit $? ; +} + +if(!open (CMMFILE, "$cmmfile") ) { + print "[main] Failed to open $cmmfile\n"; + exit 1; +} +my $offset = 0; +my $prst=0; +if($subproc){ + do{ + seek(CMMFILE,$offset,0); + while(my $line = ){ + chomp($line); + format_cmd_output($line, $nocolor); + } + $offset=tell; + }while(waitpid($subproc, WNOHANG)==0) +} +close(CMMFILE); + +unlink($cmmfile); +exit 0; +