2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-05-22 19:52:03 +00:00
xcat-core/xCAT-probe/lib/perl/probe_utils.pm
2016-09-23 02:36:52 -04:00

547 lines
15 KiB
Perl

package probe_utils;
# IBM(c) 2016 EPL license http://www.eclipse.org/legal/epl-v10.html
use strict;
use File::Path;
use File::Copy;
use Time::Local;
use Socket;
#-----------------------------------------
=head3
Description:
Format output message depending on probe framework requirement
Format is [<flag>] : <message>
The valid <flag> are debug, warning, failed, info and ok
Arguments:
output: where should the message be output
The vaild values are:
stdout : print message to STDOUT
a file name: print message to the specified "file name"
tag: the type of message, the valid values are:
d: debug
w: warning
f: failed
o: ok
i: info
If tag is NULL, output message without a tag
msg: the information need to output
Returns:
1 : Failed
0 : success
=cut
#----------------------------------------
sub send_msg {
my $output = shift;
$output = shift if (($output) && ($output =~ /probe_utils/));
my $tag = shift;
my $msg = shift;
my $flag="";
if ($tag eq "d") {
$flag = "[debug] :";
} elsif ($tag eq "w") {
$flag = "[warning]:";
} elsif ($tag eq "f") {
$flag = "[failed] :";
} elsif ($tag eq "o") {
$flag = "[ok] :";
} elsif ($tag eq "i") {
$flag = "[info] :";
}
if ($output eq "stdout") {
print "$flag$msg\n";
} elsif($output) {
syswrite $output, "$flag$msg\n";
} else {
if (!open(LOGFILE, ">> $output")) {
return 1;
}
print LOGFILE "$flag$msg\n";
close LOGFILE;
}
return 0;
}
#------------------------------------------
=head3
Description:
Test if a string is a IP address
Arguments:
addr: the string want to be judged
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_ip_addr {
my $addr = shift;
$addr = shift if (($addr) && ($addr =~ /probe_utils/));
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:
Test if a IP address belongs to a network
Arguments:
net : network address, such like 10.10.10.0
mask: network mask. suck like 255.255.255.0
ip: a ip address
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_ip_belong_to_net {
my $net = shift;
$net = shift if (($net) && ($net =~ /probe_utils/));
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 (!is_ip_addr($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
Arguments:
None
Returns:
A string, include value are sles, redhat and ubuntu
=cut
#------------------------------------------
sub get_os {
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:
Test if a IP address is a static IP address
Arguments:
ip: a ip address
nic: the network adapter which ip belongs to
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_static_ip {
my $ip = shift;
$ip = shift if (($ip) && ($ip =~ /probe_utils/));
my $nic = shift;
my $os = get_os();
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:
Test if SELinux is opened in current operating system
Arguments:
None
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_selinux_enable {
if (-e "/usr/sbin/selinuxenabled") {
`/usr/sbin/selinuxenabled`;
if ($? == 0) {
return 1;
} else {
return 0;
}
} else {
return 0;
}
}
#------------------------------------------
=head3
Description:
Test if firewall is opened in current operating system
Arguments:
None
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_firewall_open {
my $output;
my $rst = 0;
my $output = `iptables -nvL -t filter 2>&1`;
`echo "$output" |grep "Chain INPUT (policy ACCEPT" > /dev/null 2>&1`;
$rst = 1 if ($?);
`echo "$output" |grep "Chain FORWARD (policy ACCEPT" > /dev/null 2>&1`;
$rst = 1 if ($?);
`echo "$output" |grep "Chain OUTPUT (policy ACCEPT" > /dev/null 2>&1`;
$rst = 1 if ($?);
return $rst;
}
#------------------------------------------
=head3
Description:
Test if http service is ready to use in current operating system
Arguments:
ip: http server's ip
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_http_ready {
my $mnip = shift;
$mnip = shift if (($mnip) && ($mnip =~ /probe_utils/));
my $http = "http://$mnip/install/postscripts/syslog";
rename("./syslog", "./syslog.org") if (-e "./syslog");
my $outputtmp = `wget $http 2>&1`;
my $rst = $?;
if (($outputtmp =~ /200 OK/) && (!$rst) && (-e "./syslog")) {
unlink("./syslog");
rename("./syslog.org", "./syslog") if (-e "./syslog.org");
return 1;
} else {
rename("./syslog.org", "./syslog") if (-e "./syslog.org");
return 0;
}
}
#------------------------------------------
=head3
Description:
Test if tftp service is ready to use in current operating system
Arguments:
ip: tftp server's ip
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_tftp_ready {
my $mnip = shift;
$mnip = shift if (($mnip) && ($mnip =~ /probe_utils/));
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:
Test if DNS service is ready to use in current operating system
Arguments:
ip: DNS server's ip
Returns:
1 : yes
0 : no
=cut
#------------------------------------------
sub is_dns_ready {
my $mnip = shift;
$mnip = shift if (($mnip) && ($mnip =~ /probe_utils/));
my $serverip = shift;
my $hostname = shift;
my $domain = shift;
my $output = `nslookup $mnip $serverip 2>&1`;
if ($?) {
return 0;
} else {
chomp($output);
my $tmp = grep {$_ =~ "Server:[\t\s]*$serverip"} split(/\n/, $output);
return 0 if ($tmp == 0);
$tmp = grep {$_ =~ "name = $hostname\.$domain"} split(/\n/, $output);
return 0 if ($tmp == 0);
return 1;
}
}
#------------------------------------------
=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 = unpack("N", inet_aton($mask));
my $bin_ip = unpack("N", inet_aton($ip));
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;
}
#------------------------------------------
=head3
Description:
Check if the free space of specific directory is more than expected value
Arguments:
targetdir: The directory needed to be checked
expect_free_space: the expected free space for above directory
Returns:
0: the free space of specific directory is less than expected value
1: the free space of specific directory is more than expected value
2: the specific directory isn't mounted on standalone disk. it is a part of "/"
=cut
#------------------------------------------
sub is_dir_has_enough_space{
my $targetdir=shift;
$targetdir = shift if (($targetdir) && ($targetdir =~ /probe_utils/));
my $expect_free_space = shift;
my @output = `df -k`;
foreach my $line (@output){
chomp($line);
my @line_array = split(/\s+/, $line);
if($line_array[5] =~ /^$targetdir$/){
my $left_space = $line_array[3]/1048576;
if($left_space >= $expect_free_space){
return 1;
}else{
return 0;
}
}
}
return 2;
}
#------------------------------------------
=head3
Description:
Convert input time format to the number of non-leap seconds since whatever time the system considers to be the epoch
the format of input time are two kinds
one like "Aug 15 02:43:31", another likes "15/Aug/2016:01:10:24"
Arguments:
timestr: the time format need to be converted
yday: the year of current time.
Returns:
the number of non-leap seconds since whatever time the system considers to be the epoch
=cut
#------------------------------------------
sub convert_to_epoch_seconds {
my $timestr=shift;
$timestr = shift if (($timestr) && ($timestr =~ /probe_utils/));
my $yday=shift;
my $ref_seconds=shift;
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);
if($timestr =~/(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/){
($mday,$dday,$h,$m,$s)=($1,$2,$3,$4,$5);
$epoch_seconds = timelocal($s,$m,$h,$dday,$monthsmap{$mday},$yday);
if($epoch_seconds>$ref_seconds){
$yday-=1;
$epoch_seconds = timelocal($s,$m,$h,$dday,$monthsmap{$mday},$yday);
}
}elsif($timestr =~ /(\d+)\/(\w+)\/(\d+):(\d+):(\d+):(\d+)/){
$epoch_seconds = timelocal($6,$5,$4,$1,$monthsmap{$2},($3-1900));
}
return $epoch_seconds;
}
#------------------------------------------
=head3
Description:
Convert node range in Regular Expression to a node name array
Arguments:
noderange : the range of node
Returns:
An array which contains each node name
=cut
#------------------------------------------
sub parse_node_range {
my $noderange = shift;
$noderange= shift if (($noderange) && ($noderange =~ /probe_utils/));
my @nodeslist = `nodels $noderange`;
chomp @nodeslist;
return @nodeslist;
}
1;