#!/usr/bin/php
<?php
/************* Librarie */
function error_message($message)
{
	fwrite(STDERR,"FAILED  - $message\n");
}

function success_message($message)
{
	fwrite(STDOUT,"SUCCESS - $message\n");
}

/************* Functions de callbacks */
//General configuration
define('PROCESS_RUN',"/etc/init.d/ecatp-client restart");
define('PROCESS_PID_FILE','/var/run/ecatp-client.pid');

//Check_process configuration
define('PROCESS_MEM_MAX',20);
define('PROCESS_MEM_RANGE',10);
define('PROCESS_CPU_MAX',95);
define('PROCESS_CPU_RANGE',90);
define('PROCESS_TMP_FILE',"/tmp/gesa/watchdog_ecatp");

define('UNITY_SWAP_MAX',20);
define('UNITY_ZOMBIE_MAX',200);

//Check_establiched configuration
define("REMOTE_PORT",'443|2080');
define("PROGRAM","ecatp-cl");
define("TIMEOUT","10");
define("SEND_Q_LIMIT",50);

define("TRESHOLD_EXEC_SERVICE",300);
define("LAST_EXEC_DATA_FILE",'/tmp/gesa/lastexec');

//function check process nb,memory and cpu
function check_process(){
	$pid=@trim(file_get_contents(PROCESS_PID_FILE));
	if(empty($pid)){
		error_message('Process no started or unable to read pid in '.PROCESS_PID_FILE);
		return false;
	}

	$last_exec_plugin = 0; // 01/01/1970, c'est à dire jamais, last_time sera égal à quelques dizaines d'années
	if (is_readable(LAST_EXEC_DATA_FILE) ){
   		 $last_exec_plugin = trim(file_get_contents(LAST_EXEC_DATA_FILE));
	}
	$now = time();
	$last_time = $now - $last_exec_plugin;

	if( $last_time > TRESHOLD_EXEC_SERVICE ){
    		error_message("Last service run age is $last_time sec. Treshold is ".TRESHOLD_EXEC_SERVICE);
    		return false;
	}

	$output=exec("ps h --pid $pid o %cpu,%mem".'|tr -s " " " "');

	if( empty($output) ){
		error_message("Process $pid not found");
		return false;
	}

	$parsing=explode(" ",trim($output));
	$p_cpu=$parsing[0];
	$p_mem=$parsing[1];

	if($p_mem > PROCESS_MEM_MAX){
		error_message("Memory usage $p_mem > max (".PROCESS_MEM_MAX.')');
		return false;
	}

	if($p_cpu > PROCESS_CPU_MAX){
		error_message("CPU usage $p_cpu > max (".PROCESS_CPU_MAX.')');
		return false;
	}

	$content_file=@file_get_contents(PROCESS_TMP_FILE);
	if(!empty($content_file)) $first_data=json_decode($content_file,true);

	if(isset($first_data["pid"])&&$first_data["pid"]==$pid){
		$cpu_rising = $p_cpu - $first_data["cpu"];
		$mem_rising = $p_mem - $first_data["mem"];

		if( $mem_rising > PROCESS_MEM_RANGE ){
			error_message("MEM rising $mem_rising > max (".PROCESS_MEM_RANGE.')');
			return false;
		}

		if( $cpu_rising > PROCESS_CPU_RANGE ){
			error_message("CPU rising $cpu_rising > max (".PROCESS_CPU_RANGE.')');
			return false;
		}
	}
	else{
		$data = array("pid"=>$pid,"cpu"=>$p_cpu,"mem"=>$p_mem);
		file_put_contents(PROCESS_TMP_FILE,json_encode($data));
	}

	success_message("PROCESS:No problem for process $pid cpu_usage = $p_cpu% mem_usage = $p_mem%");
	return true;
}

//function check url presence.
function check_cloudurl(){
	$content = file_get_contents(FILE_CLOUDURL_PATH);
	if( $content == FALSE ) {
		error_message('Unable to read file '.FILE_CLOUDURL_PATH.'.');
		return FALSE;
	}

	$url=trim($content);
	if(filter_var("https://$url", FILTER_VALIDATE_URL) === FALSE){
		error_message("$url isn't valid. The content of file ".FILE_CLOUDURL_PATH.' must be a valid URL');
		return FALSE;
	}

	success_message("URL $url found in file ".FILE_CLOUDURL_PATH.".");
	return TRUE;
}

//function check connection established
function check_established(){
	$program=PROGRAM;
	$port=REMOTE_PORT;
	$status='ESTABLISHED';
	sleep(TIMEOUT);
	$output=exec('netstat -tnp 2>/dev/null|grep '.PROGRAM.'|tr -s " " " "|cut -d " " -f3,5-7|'."egrep '".REMOTE_PORT."'|grep $status",$all_output);
	if(empty($output)){
		error_message("Client '$program' not connected on remote port $port");
		return false;
	}

	$arr=explode(" ",$output,2);
	$output=$arr[1];

	if( $arr[0] > SEND_Q_LIMIT ) {
		error_message("Limit for TCP Send Queue reached ( $arr[0] > ".SEND_Q_LIMIT." )");
                return false;
	}

	success_message("CONNECTED on $output");
	return true;
}

function download_cloudUrl(){
	exec(CMD_DOWNLOAD_FILE,$output,$ret);
	if($ret==0) success_message("Download cloud URL success");
	else error_message("Unable get cloud URL");
	return ($ret==0);
}

function check_zombie(){
        $output=array();
        exec("ps aux | awk '\"[Zz]\" ~ $8'",$output);
        $zombies = count($output);
        if($zombies > UNITY_ZOMBIE_MAX)
        {
                error_message("Too many zombie processes : ".$zombies." > ".UNITY_ZOMBIE_MAX);
                return false;
        }
        success_message("Zombie processes number OK: ".$zombies." < ".UNITY_ZOMBIE_MAX);
        return true;
}

function check_swap(){
        $output=array();
        exec("/usr/local/gesa/plugins/check_snmp_mem.pl -H 127.0.0.1 -C public -w 98,40 -c 99,".UNITY_SWAP_MAX,$output,$ret_val);
        if($ret_val==2)
        {
                error_message("Unity SWAP (>".UNITY_SWAP_MAX.")");
                return false;
        }
        success_message("SWAP Unity OK (<".UNITY_SWAP_MAX.")");
        return true;
}

function restart_unity(){
        exec("shutdown -r +1",$output,$ret);
        if($ret==0)success_message("Restart unity success");
        else error_message("Unable to restart unity");
        return ($ret==0);
}

/************* Configuration du daemon */
$callbacks_functions = array();
$callbacks_functions["check_swap"]="restart_unity";
$callbacks_functions["check_cloudurl"]="download_cloudUrl";
$callbacks_functions["check_process"]="restart_daemon";
$callbacks_functions["check_established"]="restart_daemon";
$callbacks_functions["check_zombie"]="restart_daemon";

$action = $argv[1];
if($action =='test')
{
	$result = check_process();
	if($result==TRUE)
	{
		$result = check_established();
		if($result==TRUE)
		{
			$result = check_zombie();
			if($result==TRUE)
			{
				exit(0);
			}
			else
			{
				exit(1);
			}
		}
		else
		{
			exit(1);
		}
	}
	else
	{
		exit(1);
	}
}
elseif($action =='rescue')
{
	exec(PROCESS_RUN. " 2> /dev/null 1>/dev/null",$output,$ret);
	$output=implode("\n",$output);
    if($ret==0)
    {
		success_message("Restart daemon success");
		exit(0);
	}
    else
    {
		error_message("Unable to restart daemon");
		exit(1);
	}
}
else
{
	error_message("BAD COMMAND");
	exit(1);
}
?>
