mirror of
https://github.com/xcat2/xcat-core.git
synced 2025-05-21 19:22:05 +00:00
759 lines
22 KiB
Perl
759 lines
22 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;
|
|
use List::Util qw/sum/;
|
|
|
|
#-----------------------------------------
|
|
|
|
=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;
|
|
|
|
`which nmcli > /dev/null 2>&1`;
|
|
unless ($?) {
|
|
my $device_connection = `nmcli device show $nic 2>&1 | grep GENERAL.CONNECTION`;
|
|
my $net_name;
|
|
if ($device_connection =~ /GENERAL.CONNECTION:\s*(.+)/) {
|
|
$net_name = $1;
|
|
}
|
|
if ($net_name) {
|
|
my $ipv4_method = `nmcli con show "$net_name" 2>&1 | grep -E 'ipv4.method'`;
|
|
unless ($?) {
|
|
if ($ipv4_method =~ /manual/) {
|
|
$rst = 1;
|
|
}
|
|
return $rst;
|
|
}
|
|
}
|
|
}
|
|
|
|
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|none/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
|
|
errormsg_ref: (output attribute) if there is something wrong for HTTP service, this attribute save the possible reason.
|
|
Returns:
|
|
1 : yes
|
|
0 : no
|
|
=cut
|
|
|
|
#------------------------------------------
|
|
sub is_http_ready {
|
|
my $mnip = shift;
|
|
$mnip = shift if (($mnip) && ($mnip =~ /probe_utils/));
|
|
my $installdir = shift;
|
|
my $errormsg_ref = shift;
|
|
|
|
my $http = "http://$mnip/$installdir/postscripts/syslog";
|
|
my %httperror = (
|
|
"400" => "The request $http could not be understood by the server due to malformed syntax",
|
|
"401" => "The request requires user authentication.",
|
|
"403" => "The server understood the request, but is refusing to fulfill it.",
|
|
"404" => "The server has not found anything matching the test Request-URI $http.",
|
|
"405" => "The method specified in the Request-Line $http is not allowe.",
|
|
"406" => "The method specified in the Request-Line $http is not acceptable.",
|
|
"407" => "The wget client must first authenticate itself with the proxy.",
|
|
"408" => "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.",
|
|
"409" => "The request could not be completed due to a conflict with the current state of the resource.",
|
|
"410" => "The requested resource $http is no longer available at the server and no forwarding address is known.",
|
|
"411" => "The server refuses to accept the request without a defined Content- Length.",
|
|
"412" => "The precondition given in one or more of the request-header fields evaluated to false when it was tested on the server.",
|
|
"413" => "The server is refusing to process a request because the request entity is larger than the server is willing or able to process.",
|
|
"414" => "The server is refusing to service the request because the Request-URI is longer than the server is willing to interpret.",
|
|
"415" => "The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.",
|
|
"416" => "Requested Range Not Satisfiable",
|
|
"417" => "The expectation given in an Expect request-header field could not be met by this server",
|
|
"500" => "The server encountered an unexpected condition which prevented it from fulfilling the request.",
|
|
"501" => "The server does not recognize the request method and is not capable of supporting it for any resource.",
|
|
"502" => "The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the reques.",
|
|
"503" => "The server is currently unable to handle the request due to a temporary overloading or maintenance of the server.",
|
|
"504" => "The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI or some other auxiliary server it needed to access in attempting to complete the request.",
|
|
"505" => "The server does not support, or refuses to support, the HTTP protocol version that was used in the request message.");
|
|
|
|
my $tmpdir = "/tmp/xcatprobe$$/";
|
|
if(! mkpath("$tmpdir")){
|
|
$$errormsg_ref = "Prepare test environment error: $!";
|
|
return 0;
|
|
}
|
|
my @outputtmp = `wget -O $tmpdir/syslog $http 2>&1`;
|
|
my $rst = $?;
|
|
$rst = $rst >> 8;
|
|
|
|
if ((!$rst) && (-e "$tmpdir/syslog")) {
|
|
unlink("$tmpdir/syslog");
|
|
rmdir ("$tmpdir");
|
|
return 1;
|
|
} elsif ($rst == 4) {
|
|
$$errormsg_ref = "Network failure, the server refuse connection. Please check if httpd service is running first.";
|
|
} elsif ($rst == 5) {
|
|
$$errormsg_ref = "SSL verification failure, the server refuse connection";
|
|
} elsif ($rst == 6) {
|
|
$$errormsg_ref = "Username/password authentication failure, the server refuse connection";
|
|
} elsif ($rst == 8) {
|
|
my $returncode = $outputtmp[2];
|
|
chomp($returncode);
|
|
$returncode =~ s/.+(\d\d\d).+/$1/g;
|
|
if(exists($httperror{$returncode})){
|
|
$$errormsg_ref = $httperror{$returncode};
|
|
}else{
|
|
#should not hit this block normally
|
|
$$errormsg_ref = "Unknown return code of wget <$returncode>.";
|
|
}
|
|
}
|
|
unlink("$tmpdir/syslog");
|
|
if(! rmdir ("$tmpdir")){
|
|
$$errormsg_ref .= " Clean test environment error(rmdir $tmpdir): $!";
|
|
}
|
|
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/));
|
|
my $tftpdir = shift;
|
|
my $test_dir = $tftpdir . "/tftptest/";
|
|
system("mkdir -p $test_dir");
|
|
|
|
rename("/$test_dir/tftptestt.tmp", "/$test_dir/tftptestt.tmp.old") if (-e "/$test_dir/tftptestt.tmp");
|
|
rename("./tftptestt.tmp", "./tftptestt.tmp.old") if (-e "./tftptestt.tmp");
|
|
|
|
system("touch /$test_dir/tftptestt.tmp");
|
|
my $output = `tftp -4 -v $mnip -c get /tftptest/tftptestt.tmp 2>&1`;
|
|
if ((!$?) && (-e "./tftptestt.tmp")) {
|
|
unlink("./tftptestt.tmp");
|
|
rename("./tftptestt.tmp.old", "./tftptestt.tmp") if (-e "./tftptestt.tmp.old");
|
|
rename("/$test_dir/tftptestt.tmp.old", "/$test_dir/tftptestt.tmp") if (-e "/$test_dir/tftptestt.tmp.old");
|
|
return 1;
|
|
} else {
|
|
rename("./tftptestt.tmp.old", "./tftptestt.tmp") if (-e "./tftptestt.tmp.old");
|
|
rename("/$test_dir/tftptestt.tmp.old", "/$test_dir/tftptestt.tmp") if (-e "/$test_dir/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:
|
|
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:
|
|
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 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;
|
|
}
|
|
|
|
#------------------------------------------
|
|
|
|
=head3
|
|
Description:
|
|
Test if ntp service is ready to use in current operating system
|
|
Arguments:
|
|
errormsg_ref: (output attribute) if there is something wrong for ntp service, this attribute save the possible reason.
|
|
Returns:
|
|
1 : yes
|
|
0 : no
|
|
=cut
|
|
|
|
#------------------------------------------
|
|
sub is_ntp_ready{
|
|
my $errormsg_ref = shift;
|
|
$errormsg_ref= shift if (($errormsg_ref) && ($errormsg_ref =~ /probe_utils/));
|
|
|
|
my $cmd = 'ntpq -c "rv 0"';
|
|
$| = 1;
|
|
|
|
#wait 5 seconds for ntpd synchronize at most
|
|
for (my $i = 0; $i < 5; ++$i) {
|
|
if(!open(NTP, $cmd." 2>&1 |")){
|
|
$$errormsg_ref = "Can't start ntpq: $!";
|
|
return 0;
|
|
}else{
|
|
while(<NTP>) {
|
|
chomp;
|
|
if (/^associd=0 status=(\S{4}) (\S+),/) {
|
|
my $leap=$2;
|
|
|
|
last if ($leap =~ /(sync|leap)_alarm/);
|
|
|
|
if ($leap =~ /leap_(none|((add|del)_sec))/){
|
|
close(NTP);
|
|
return 1;
|
|
}
|
|
|
|
#should not hit below 3 lines normally
|
|
$$errormsg_ref = "Unexpected ntpq output ('leap' status <$leap>), please contact xCAT team";
|
|
close(NTP);
|
|
return 0;
|
|
}elsif(/Connection refused/) {
|
|
$$errormsg_ref = "ntpd service is not running! Please setup ntp in current node";
|
|
close(NTP);
|
|
return 0;
|
|
}else{
|
|
#should not hit this block normally
|
|
$$errormsg_ref = "Unexpected ntpq output <$_>, please contact xCAT team";
|
|
close(NTP);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
close(NTP);
|
|
sleep 1;
|
|
}
|
|
$$errormsg_ref = "ntpd did not synchronize.";
|
|
return 0;
|
|
}
|
|
|
|
#------------------------------------------
|
|
|
|
=head3
|
|
Description:
|
|
Test if rsyslog service is ready to use in current operating system
|
|
Arguments:
|
|
errormsg_ref: if there is something wrong for ntp service, this attribute save the possible reason.
|
|
Returns:
|
|
1 : yes
|
|
0 : no
|
|
=cut
|
|
|
|
#------------------------------------------
|
|
sub is_rsyslog_ready {
|
|
my $errormsg_ref = shift;
|
|
$errormsg_ref= shift if (($errormsg_ref) && ($errormsg_ref =~ /probe_utils/));
|
|
|
|
my $is_active = 1;
|
|
my $tmp = `pidof systemd`;
|
|
chomp($tmp);
|
|
if ($tmp) {
|
|
`systemctl is-active --quiet rsyslog 2>&1`;
|
|
if ($?) {
|
|
$is_active = 0;
|
|
}
|
|
} else {
|
|
my $output = `service rsyslog status 2>&1 | grep "Active: active (running)"`;
|
|
if (!$output) {
|
|
$is_active = 0;
|
|
}
|
|
}
|
|
|
|
if (!$is_active) {
|
|
$$errormsg_ref = "rsyslog service is not running! Please check on current node";
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
#------------------------------------------
|
|
|
|
=head3
|
|
Description:
|
|
Convert second to time
|
|
Arguments:
|
|
second_in : the time in seconds
|
|
Returns:
|
|
xx:xx:xx xx hours xx minutes xx seconds
|
|
=cut
|
|
|
|
#------------------------------------------
|
|
sub convert_second_to_time {
|
|
my $second_in = shift;
|
|
$second_in = shift if (($second_in) && ($second_in =~ /probe_utils/));
|
|
my @time = ();
|
|
my $result;
|
|
|
|
if ($second_in == 0) {
|
|
return "00:00:00";
|
|
}
|
|
|
|
my $count = 0;
|
|
while ($count < 3) {
|
|
my $tmp_second;
|
|
if ($count == 2) {
|
|
$tmp_second = $second_in % 100;
|
|
} else {
|
|
$tmp_second = $second_in % 60;
|
|
}
|
|
|
|
if ($tmp_second < 10) {
|
|
push @time, "0$tmp_second";
|
|
} else {
|
|
push @time, "$tmp_second";
|
|
}
|
|
|
|
$second_in = ($second_in - $tmp_second) / 60;
|
|
$count++;
|
|
}
|
|
|
|
my @time_result = reverse @time;
|
|
$result = join(":", @time_result);
|
|
|
|
return $result;
|
|
}
|
|
|
|
#------------------------------------------
|
|
|
|
=head3
|
|
Description:
|
|
print table
|
|
Arguments:
|
|
content: double dimensional array
|
|
has_title: whether has title in content
|
|
|
|
eg: @content = ($title,
|
|
@content1,
|
|
@content2,
|
|
......
|
|
);
|
|
$has_title = 1;
|
|
print_table(\@content, $has_title);
|
|
|
|
or @content = (@content1,
|
|
@content2,
|
|
......
|
|
);
|
|
$has_title = 0;
|
|
print_table(\@content, $has_title);
|
|
|
|
Ouput:
|
|
--------------------------
|
|
| xxxxxxx |
|
|
--------------------------
|
|
| xxx | xxxx | xx | xx |
|
|
--------------------------
|
|
| xx | xxxx | xxxx | xx |
|
|
--------------------------
|
|
|
|
or
|
|
|
|
--------------------------
|
|
| xxx | xxxx | xx | xx |
|
|
--------------------------
|
|
| xx | xxxx | xxxx | xx |
|
|
--------------------------
|
|
|
|
=cut
|
|
|
|
#------------------------------------------
|
|
sub print_table {
|
|
my $content = shift;
|
|
$content = shift if (($content) && ($content =~ /probe_utils/));
|
|
my $has_title = shift;
|
|
my $title;
|
|
|
|
if ($has_title) {
|
|
$title = shift(@$content);
|
|
}
|
|
|
|
my @length_array;
|
|
foreach my $row (@$content) {
|
|
for (my $i = 0; $i < @{$row}; $i++) {
|
|
my $ele_length = length(${$row}[$i]);
|
|
$length_array[$i] = $ele_length if ($length_array[$i] < $ele_length);
|
|
}
|
|
}
|
|
|
|
my @content_new;
|
|
my @row_new;
|
|
my $row_line;
|
|
my $whole_length;
|
|
foreach my $row (@$content) {
|
|
@row_new = ();
|
|
for (my $i = 0; $i < @{$row}; $i++) {
|
|
push @row_new, ${$row}[$i] . " " x ($length_array[$i] - length(${$row}[$i]));
|
|
}
|
|
$row_line = "| " . join(" | ", @row_new) . " |";
|
|
push @content_new, $row_line;
|
|
}
|
|
$whole_length = length($row_line);
|
|
|
|
my $title_new;
|
|
my $title_length = length($title);
|
|
if ($has_title) {
|
|
if ($whole_length - 1 <= $title_length) {
|
|
$title_new = $title;
|
|
} else {
|
|
$title_new = " " x (($whole_length - 2 - $title_length)/2) . "$title";
|
|
$title_new .= " " x ($whole_length - 2 - length($title_new));
|
|
$title_new = "|" . $title_new . "|";
|
|
}
|
|
}
|
|
|
|
my $format_line = "-" x $whole_length;
|
|
print $format_line . "\n" if ($has_title);
|
|
print $title_new . "\n" if ($has_title);
|
|
print $format_line . "\n";
|
|
foreach (@content_new) {
|
|
print $_ . "\n";
|
|
}
|
|
print $format_line . "\n";
|
|
}
|
|
|
|
1;
|