mirror of
https://github.com/unraid/webgui.git
synced 2025-12-31 06:30:10 -06:00
187 lines
7.9 KiB
PHP
Executable File
187 lines
7.9 KiB
PHP
Executable File
#!/usr/bin/php -q
|
|
<?PHP
|
|
/* Copyright 2005-2024, Lime Technology
|
|
* Copyright 2012-2024, Bergware International.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License version 2,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*/
|
|
?>
|
|
<?
|
|
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
|
require_once "$docroot/webGui/include/Wrappers.php";
|
|
|
|
$var = (array)@parse_ini_file("/var/local/emhttp/var.ini");
|
|
$disks = (array)@parse_ini_file("/var/local/emhttp/disks.ini",true);
|
|
|
|
require_once "$docroot/webGui/include/CustomMerge.php";
|
|
|
|
$script = "$docroot/webGui/scripts/notify";
|
|
// this command will set the $notify array
|
|
extract(parse_plugin_cfg("dynamix",true));
|
|
$output = _var($notify,'report');
|
|
$server = strtoupper(_var($var,'NAME','tower'));
|
|
$data = [];
|
|
$parity = $pools = false;
|
|
$error0 = $error1 = $error2 = $error3 = 0;
|
|
|
|
function plus($val, $word, $last) {
|
|
return $val>0 ? (($val || $last) ? ($val.' '.$word.($val!=1?'s':'').($last ?'':', ')) : '') : '';
|
|
}
|
|
function my_temp($value) {
|
|
global $display;
|
|
if ($value=='*') return ' - standby';
|
|
$unit = _var($display,'unit','C');
|
|
return ' - active '.($unit=='F' ? fahrenheit($value) : str_replace('.',_var($display,'number','.,')[0], $value)).' '.$unit;
|
|
}
|
|
function my_disk($name) {
|
|
return ucfirst(preg_replace('/(\d+)$/',' $1',$name));
|
|
}
|
|
function my_scale($value, &$unit, $precision = NULL) {
|
|
global $display;
|
|
$scale = _var($display,'scale',-1);
|
|
$number = _var($display,'number','.,');
|
|
$units = ['B','KB','MB','GB','TB','PB'];
|
|
if ($scale==0 && $precision===NULL) {
|
|
$unit = '';
|
|
return number_format($value, 0, $number[0], ($value>=10000 ? $number[1] : ''));
|
|
} else {
|
|
$base = $value ? floor(log($value, 1000)) : 0;
|
|
if ($scale>0 && $base>$scale) $base = $scale;
|
|
$value = round($value/pow(1000, $base), $precision===NULL ? 2 : $precision);
|
|
if ($value>=1000 && $scale<0) { $value = 1; $base++; }
|
|
$unit = $units[$base];
|
|
return number_format($value, $precision===NULL ? (($value-intval($value)==0 || $value>=100) ? 0 : ($value>=10 ? 1 : 2)) : $precision, $number[0], ($value>=10000 ? $number[1] : ''));
|
|
}
|
|
}
|
|
function my_check($time,$speed) {
|
|
if (!$time) return 'unavailable (no parity-check entries logged)';
|
|
$days = floor($time/86400);
|
|
$hmss = $time-$days*86400;
|
|
$hour = floor($hmss/3600);
|
|
$mins = floor($hmss/60)%60;
|
|
$secs = $hmss%60;
|
|
return plus($days,'day',($hour|$mins|$secs)==0).plus($hour,'hour',($mins|$secs)==0).plus($mins,'minute',$secs==0).plus($secs,'second',true).". Average speed: $speed";
|
|
}
|
|
function my_time($time) {
|
|
global $display;
|
|
$date = my_date(_var($display,'date').(_var($display,'date')!='%c' ? ", "._var($display,'time') : ""), $time);
|
|
$now = new DateTime("@".intval(time()/86400)*86400);
|
|
$last = new DateTime("@".intval($time/86400)*86400);
|
|
$days = date_diff($last,$now)->format('%a');
|
|
switch (true) {
|
|
case ($days<0):
|
|
return $date;
|
|
case ($days==0):
|
|
return "$date (today)";
|
|
case ($days==1):
|
|
return "$date (yesterday)";
|
|
default:
|
|
return "$date ($days days ago)";
|
|
}
|
|
}
|
|
function my_clock($time) {
|
|
if (!$time) return 'less than a minute';
|
|
$days = floor($time/1440);
|
|
$hour = floor($time/60)%24;
|
|
$mins = $time%60;
|
|
return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true);
|
|
}
|
|
|
|
function my_array(&$disk) {
|
|
global $data,$display,$error0,$error1,$error2,$error3;
|
|
$name = _var($disk,'name');
|
|
[$hotNVME,$maxNVME] = _var($disk,'transport')=='nvme' ? get_nvme_info(_var($disk,'device'),'temp') : [-1,-1];
|
|
$hot = _var($disk,'hotTemp',-1)>=0 ? $disk['hotTemp'] : ($hotNVME>=0 ? $hotNVME : (_var($disk,'rotational',1)==0 && $display['hotssd']>=0 ? $display['hotssd'] : $display['hot']));
|
|
$max = _var($disk,'maxTemp',-1)>=0 ? $disk['maxTemp'] : ($maxNVME>=0 ? $maxNVME : (_var($disk,'rotational',1)==0 && $display['maxssd']>=0 ? $display['maxssd'] : $display['max']));
|
|
if (strpos(_var($disk,'status'),'_NP')!==false) return false;
|
|
$temp = _var($disk,'temp');
|
|
if ($max>0 && $temp>=$max) {
|
|
$fail = ' (disk is overheated';
|
|
$error0++;
|
|
} elseif ($hot>0 && $temp>=$hot) {
|
|
$fail = ' (disk is hot';
|
|
$error1++;
|
|
} else {
|
|
$fail = '';
|
|
}
|
|
if (_var($disk,'numErrors',0)>0) {
|
|
if ($fail) $fail .= ', '; else $fail = ' (';
|
|
$fail .= 'disk has read errors';
|
|
$error2++;
|
|
}
|
|
if ($fail) $fail .= ')';
|
|
$status = $fail ? ' [NOK]' : ' [OK]';
|
|
$color = strtok(_var($disk,'color'),'-');
|
|
if ($color=='red'||$color=='yellow') {$error3++; $status = ' ['.str_replace(['NP_','_'],['',' '],_var($disk,'status')).']';}
|
|
$info = _var($disk,'id')." ("._var($disk,'device').")";
|
|
if ($info==" ()") $info = 'No device identification present';
|
|
$data[] = my_disk($name)." - $info".my_temp($temp).$fail.$status;
|
|
return true;
|
|
}
|
|
|
|
// generate report of array devices
|
|
foreach ($disks as $disk) if (_var($disk,'type')=='Parity') $parity |= my_array($disk);
|
|
foreach ($disks as $disk) if (_var($disk,'type')=='Data') my_array($disk);
|
|
foreach ($disks as $disk) if (_var($disk,'type')=='Cache') $pools |= my_array($disk);
|
|
|
|
$size = count($data);
|
|
|
|
// generate parity report
|
|
$data[] = '';
|
|
$mdResync = _var($var,'mdResync',0);
|
|
$action = preg_split('/\s+/',_var($var,'mdResyncAction'));
|
|
if ($mdResync>0) {
|
|
$mdResyncPos = _var($var,'mdResyncPos',0);
|
|
$mdResyncDb = _var($var,'mdResyncDb',0);
|
|
$mdResyncDt = _var($var,'mdResyncDt',0);
|
|
switch ($action[0]) {
|
|
case "recon": $mode = $action[1]=='P' ? 'Parity-Sync' : 'Data-Rebuild'; break;
|
|
case "check": $mode = count($action)>1 ? 'Parity-Check' : 'Read-Check'; break;
|
|
case "clear": $mode = 'Disk-Clear'; break;
|
|
default : $mode = 'Unknown'; break;
|
|
}
|
|
$data[] = $mode." in progress.";
|
|
$data[] = "Total size: ".my_scale($mdResync*1024, $unit)." $unit";
|
|
$data[] = "Elapsed time: ".my_clock(floor((time()-_var($var,'sbUpdated',0))/60));
|
|
$data[] = "Current position: ".my_scale($mdResyncPos*1024, $unit)." $unit (".number_format(($mdResyncPos/($mdResync/100+1)),1,$unraid['display']['number'][0],'')." %)";
|
|
$data[] = "Estimated speed: ".my_scale($mdResyncDb/$mdResyncDt*1024, $unit, 1)." $unit/sec";
|
|
$data[] = "Estimated finish: ".my_clock(round(((($mdResyncDt*(($mdResync-$mdResyncPos)/($mdResyncDb/100+1)))/100)/60),0));
|
|
$data[] = "Sync errors ".(_var($var,'mdResyncCorr',0)==0 ? 'detected: ' : 'corrected: ')._var($var,'sbSyncErrs',0);
|
|
} else {
|
|
$sbSynced = _var($var,'sbSynced',0);
|
|
$sbSynced2 = _var($var,'sbSynced2',0);
|
|
$sbSyncErrs = _var($var,'sbSyncErrs',0);
|
|
if (_var($var,'sbSyncExit',0)!=0) {
|
|
$data[] = "Last check incomplete on ".my_time($sbSynced2).", finding $sbSyncErrs error".($sbSyncErrs==1?'.':'s.');
|
|
$data[] = "Error code: ".$var['sbSyncExit'];
|
|
} elseif ($sbSynced==0) {
|
|
$data[] = "Parity has not been checked yet";
|
|
} elseif ($sbSynced2>0) {
|
|
if ($action[0]=='recon') {
|
|
$data[] = $action[1]=='P' ? 'Parity is invalid' : 'Data-Rebuild is invalid';
|
|
} else {
|
|
$data[] = 'Parity is valid';
|
|
}
|
|
$duration = Max($sbSynced2-$sbSynced,1);
|
|
$speed = my_scale(_var($var,'mdResyncSize',0)*1024/$duration,$unit,1)." $unit/s";
|
|
$data[] = "Last checked on ".my_time($sbSynced2).", finding $sbSyncErrs error".($sbSyncErrs==1?'.':'s.');
|
|
$data[] = "Duration: ".my_check($duration,$speed);
|
|
}
|
|
}
|
|
|
|
$word = $size==1 ? "" : "including ";
|
|
$warn = ($error0 || $error3) ? "alert" : (($error1 || $error2) ? "warning" : "normal");
|
|
$stat = $warn=="normal" ? "[PASS]" : "[FAIL]";
|
|
$info = "Array has $size disk".($size==1 ? "" : "s").($parity ? " ({$word}parity".($pools ? " & pools)" : ")") : ($pools ? " ({$word}pools)" : ""));
|
|
$message = implode('\n', $data);
|
|
$subject = "Notice [$server] - array health report $stat";
|
|
exec("$script -s ".escapeshellarg($subject)." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'");
|
|
|
|
exit(0);
|
|
?>
|