mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-04 05:12:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			895 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			895 lines
		
	
	
		
			26 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 SELinux is enforcing in current operating system
 | 
						|
    Arguments:
 | 
						|
         None
 | 
						|
    Returns:
 | 
						|
        1 : yes
 | 
						|
        0 : no
 | 
						|
=cut
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
sub is_selinux_enforcing {
 | 
						|
    my $retval = 0;
 | 
						|
    if (-e "/usr/sbin/getenforce") {
 | 
						|
        my $enforce_mode = `/usr/sbin/getenforce`;
 | 
						|
        chomp $enforce_mode;
 | 
						|
	if ($enforce_mode eq "Enforcing") {
 | 
						|
            $retval = 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return $retval;
 | 
						|
}
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
 | 
						|
=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`;
 | 
						|
 | 
						|
    if ($output =~ /DROP|RETURN/) {
 | 
						|
        # If output contains DROP or RETURN rules, assume firewall
 | 
						|
        # is blocking some traffic
 | 
						|
        $rst=1;
 | 
						|
    }
 | 
						|
    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 $httpport = shift;
 | 
						|
    my $installdir = shift;
 | 
						|
    my $errormsg_ref = shift;
 | 
						|
 | 
						|
    my $http_status = `netstat -tnlp | grep -e "httpd" -e "apache" 2>&1`;
 | 
						|
    if (!$http_status) {
 | 
						|
        $$errormsg_ref = "No HTTP listening status get by command 'netstat'";
 | 
						|
        return 0;
 | 
						|
    } elsif ($http_status !~ /\S*\s+\S*\s+\S*\s+\S*:$httpport\s+.+/) {
 | 
						|
        $$errormsg_ref = "The port defined in 'site' table HTTP is not listening";
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    my $test_file = "efibootmgr";
 | 
						|
 | 
						|
    my $http      = "http://$mnip:$httpport/$installdir/postscripts/$test_file";
 | 
						|
    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/$test_file $http 2>&1`;
 | 
						|
    my $rst       = $?;
 | 
						|
    $rst = $rst >> 8;
 | 
						|
 | 
						|
    if ((!$rst) && (-e "$tmpdir/$test_file")) {
 | 
						|
        unlink("$tmpdir/$test_file");
 | 
						|
        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/$test_file");
 | 
						|
    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("date > /$test_dir/tftptestt.tmp");
 | 
						|
    my $output = `tftp -4 -v $mnip -c get /tftptest/tftptestt.tmp 2>&1`;
 | 
						|
    if ((!$?) && (-s "./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");
 | 
						|
        system("rm -rf $test_dir");
 | 
						|
        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");
 | 
						|
        system("rm -rf $test_dir");
 | 
						|
        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 -type=A $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 chrony service is ready to use in current operating system
 | 
						|
    Arguments:
 | 
						|
        errormsg_ref: (output attribute) if there is something wrong for chrony service, this attribute save the possible reason.
 | 
						|
    Returns:
 | 
						|
        1 : yes
 | 
						|
        0 : no
 | 
						|
=cut
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
sub is_chrony_ready {
 | 
						|
    my $errormsg_ref = shift;
 | 
						|
    $errormsg_ref = shift if (($errormsg_ref) && ($errormsg_ref =~ /probe_utils/));
 | 
						|
 | 
						|
    my $chronycoutput = `chronyc tracking 2>&1`;
 | 
						|
    if ($?) {
 | 
						|
        if ($chronycoutput =~ /Cannot talk to daemon/) {
 | 
						|
            $$errormsg_ref = "chronyd service is not running! Please setup ntp in current node";
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
        $$errormsg_ref = "command 'chronyc tracking' failed, could not get status of ntp service";
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
    if ($chronycoutput =~ /Leap status     : (.+)/) {
 | 
						|
        my $status = $1;
 | 
						|
        if ($status eq "Not synchronised") {
 | 
						|
            $$errormsg_ref = "chronyd did not synchronize.";
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return 1;
 | 
						|
}
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
 | 
						|
=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:
 | 
						|
        Call get_files_recursive to get all files under given dir,
 | 
						|
        and save to target file
 | 
						|
    Arguments:
 | 
						|
        dir: the dir want to get files
 | 
						|
        target_file: the file to save files list
 | 
						|
        
 | 
						|
=cut
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
sub list_files_to_file {
 | 
						|
    my $src_dir        = shift;
 | 
						|
    $src_dir           = shift if (($src_dir) && ($src_dir =~ /probe_utils/));
 | 
						|
    my $target_file    = shift;
 | 
						|
    my $errormsg_ref   = shift;
 | 
						|
 | 
						|
    my @files = ();
 | 
						|
    get_files_recursive("$src_dir", \@files);
 | 
						|
    my $all_file = join("\n", @files);
 | 
						|
 | 
						|
    if (!open f,"> $target_file") {
 | 
						|
        $$errormsg_ref = "Can not open file $target_file to save files list"; 
 | 
						|
        return 1;
 | 
						|
    }
 | 
						|
    print f $all_file;
 | 
						|
    close f;
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
 | 
						|
=head3
 | 
						|
    Description:
 | 
						|
        Get all files under the given dir
 | 
						|
    Arguments:
 | 
						|
        dir: the dir want to get files
 | 
						|
        files_path_ref: list of all files
 | 
						|
=cut
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
sub get_files_recursive {
 | 
						|
    my $dir            = shift;
 | 
						|
    my $files_path_ref = shift;
 | 
						|
 | 
						|
    my $fd = undef;
 | 
						|
    opendir($fd, $dir);
 | 
						|
    for (; ;)
 | 
						|
    {
 | 
						|
        my $direntry = readdir($fd);
 | 
						|
        last unless (defined($direntry));
 | 
						|
        next if ($direntry =~ m/^\.\w*/);
 | 
						|
        next if ($direntry eq '..');
 | 
						|
        my $target = "$dir/$direntry";
 | 
						|
        if (-d $target) {
 | 
						|
            get_files_recursive($target, $files_path_ref);
 | 
						|
        } else {
 | 
						|
            push(@{$files_path_ref}, glob("$target\n"));
 | 
						|
        }
 | 
						|
    }
 | 
						|
    closedir($fd);
 | 
						|
}
 | 
						|
 | 
						|
#------------------------------------------
 | 
						|
 | 
						|
=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;
 |