mirror of
https://github.com/unraid/webgui.git
synced 2026-04-22 10:08:25 -05:00
Revamped dashboard page
This commit is contained in:
@@ -12,55 +12,14 @@
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
|
||||
function normalize($type,$count) {
|
||||
$words = explode('_',$type);
|
||||
foreach ($words as &$word) $word = $word==strtoupper($word) ? $word : preg_replace(['/^(ct|cnt)$/','/^blk$/'],['count','block'],strtolower($word));
|
||||
return ucfirst(implode(' ',$words)).": ".str_replace('_',' ',strtolower($count))."\n";
|
||||
}
|
||||
function my_insert(&$source,$string) {
|
||||
$source = substr_replace($source,$string,4,0);
|
||||
}
|
||||
function my_smart(&$source,$name,$page) {
|
||||
global $var,$disks,$path,$failed,$numbers,$saved;
|
||||
$disk = &$disks[$name];
|
||||
$select = get_value($disk,'smSelect',0);
|
||||
$level = get_value($disk,'smLevel',1);
|
||||
$events = explode('|',get_value($disk,'smEvents',$numbers));
|
||||
$title = '';
|
||||
$thumb = 'good';
|
||||
$smart = "state/smart/$name";
|
||||
if (file_exists("$smart.ssa") && in_array(file_get_contents("$smart.ssa"),$failed)) {
|
||||
$title = "S.M.A.R.T health-check failed\n"; $thumb = 'bad';
|
||||
} else {
|
||||
if (empty($saved["smart"]["$name.ack"])) {
|
||||
exec("awk 'NR>7{print $1,$2,$4,$6,$9,$10}' ".escapeshellarg($smart)." 2>/dev/null", $codes);
|
||||
foreach ($codes as $code) {
|
||||
if (!$code || !is_numeric($code[0])) continue;
|
||||
list($id,$class,$value,$thres,$when,$raw) = explode(' ',$code);
|
||||
$fail = strpos($when,'FAILING_NOW')!==false;
|
||||
if (!$fail && !in_array($id,$events)) continue;
|
||||
if ($fail || ($select ? $thres>0 && $value<=$thres*$level : $raw>0)) $title .= normalize($class,$fail?$when:$raw);
|
||||
}
|
||||
if ($title) $thumb = 'alert'; else $title = "No errors reported\n";
|
||||
}
|
||||
}
|
||||
$title .= "Click for context menu";
|
||||
my_insert($source, "<span id='smart-$name' name='$page' class='$thumb'><img src=\"$path/$thumb.png\" onmouseover=\"this.style.cursor='pointer'\" title=\"$title\"></span>");
|
||||
}
|
||||
function my_usage(&$source,$used,&$disk) {
|
||||
if ($used && ($_POST['text']==2 || $_POST['text']==21)) {
|
||||
$load = substr($used,0,-1);
|
||||
$critical = $disk['critical'] ?? $_POST['critical'];
|
||||
$warning = $disk['warning'] ?? $_POST['warning'];
|
||||
if ($load >= $critical) $class = 'redbar';
|
||||
elseif ($load >= $warning) $class = 'orangebar';
|
||||
else $class = 'greenbar';
|
||||
} else $class = false;
|
||||
my_insert($source, $used ? ($_POST['text']%10==0 ? $used : "<div class='usage-disk all'><span style='width:$used'".($class?" class='$class'":"").">$used</span></div>") : "-");
|
||||
}
|
||||
function my_temp($value,$unit) {
|
||||
function my_unit($value,$unit) {
|
||||
return ($unit=='F' ? round(9/5*$value+32) : $value)." $unit";
|
||||
}
|
||||
function my_clock($time) {
|
||||
@@ -70,11 +29,11 @@ function my_clock($time) {
|
||||
$mins = $time%60;
|
||||
return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true);
|
||||
}
|
||||
function plus($val,$word,$last) {
|
||||
return $val>0?(($val||$last)?($val.' '.$word.($val!=1?'s':'').($last ?'':', ')):''):'';
|
||||
function parity_disks($disk) {
|
||||
return $disk['type']=='Parity';
|
||||
}
|
||||
function active_disks($disk) {
|
||||
return substr($disk['status'],0,7)!='DISK_NP' && preg_match('/^(Parity|Data|Cache)$/',$disk['type']);
|
||||
return substr($disk['status'],0,7)!='DISK_NP' && in_array($disk['type'],['Parity','Data','Cache']);
|
||||
}
|
||||
function find_day($D) {
|
||||
global $days;
|
||||
@@ -154,161 +113,272 @@ function stage($i) {
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
$path = '/webGui/images';
|
||||
$failed = ['FAILED','NOK'];
|
||||
|
||||
function device_name(&$disk, $array) {
|
||||
if ($array) {
|
||||
switch ($disk['type']) {
|
||||
case 'Flash' : $type = 'usb'; break;
|
||||
case 'Parity': $type = $disk['rotational'] ? 'disk' : 'nvme'; break;
|
||||
case 'Data' :
|
||||
case 'Cache' : $type = $disk['rotational'] ? ($disk['luksState'] ? 'disk-encrypted' : 'disk') : 'nvme'; break;
|
||||
}
|
||||
return "<i class='icon-$type'></i> ".my_disk($disk['name']);
|
||||
} else {
|
||||
return "<i class='icon-disk'></i> {$disk['device']}";
|
||||
}
|
||||
}
|
||||
function device_status(&$disk, &$error, &$warning) {
|
||||
global $var;
|
||||
if ($var['fsState']=='Stopped') {
|
||||
$color = 'green'; $text = 'off-line';
|
||||
} else switch ($disk['color']) {
|
||||
case 'green-on' : $color = 'green'; $text = 'active'; break;
|
||||
case 'green-blink' : $color = 'grey'; $text = 'standby'; break;
|
||||
case 'blue-on' : $color = 'blue'; $text = 'unassigned'; break;
|
||||
case 'blue-blink' : $color = 'grey'; $text = 'unassigned'; break;
|
||||
case 'yellow-on' : $color = 'yellow'; $text = 'emulated'; $warning++; break;
|
||||
case 'yellow-blink': $color = 'grey'; $text = 'emulated'; $warning++; break;
|
||||
case 'red-on' : $color = 'red'; $text = 'disabled'; $error++; break;
|
||||
case 'red-blink' : $color = 'grey'; $text = 'disabled'; $error++; break;
|
||||
case 'red-off' : $color = 'red'; $text = 'faulty'; $error++; break;
|
||||
case 'grey-off' : $color = 'grey'; $text = 'no device'; break;
|
||||
}
|
||||
return "<i class='fa fa-circle orb $color-orb middle'></i>$text";
|
||||
}
|
||||
function device_temp(&$disk, &$red, &$orange) {
|
||||
$spin = strpos($disk['color'],'blink')===false;
|
||||
$temp = $disk['temp'];
|
||||
$hot = $disk['hotTemp'] ?? $_POST['hot'];
|
||||
$max = $disk['maxTemp'] ?? $_POST['max'];
|
||||
$top = $_POST['top'] ?? 120;
|
||||
$heat = false; $color = 'green';
|
||||
if (exceed($temp,$max,$top)) {
|
||||
$heat = 'fire'; $color = 'red'; $red++;
|
||||
} elseif (exceed($temp,$hot,$top)) {
|
||||
$heat = 'fire'; $color = 'orange'; $orange++;
|
||||
}
|
||||
return ($spin && $temp>0) ? "<span class='$color-text'>".my_unit($temp,$_POST['unit'])."</span>".($heat ? "<i class='fa fa-$heat $color-text heat'></i>" : "") : "*";
|
||||
}
|
||||
function device_smart(&$disk, $name, &$fail, &$smart) {
|
||||
global $numbers,$saved;
|
||||
if (!$disk['device'] || strpos($disk['color'],'blink')) return "-";
|
||||
$failed = ['FAILED','NOK'];
|
||||
$page = $name ? 'New' : 'Device';
|
||||
$name = $name ?: $disk['name'];
|
||||
$select = get_value($name,'smSelect',0);
|
||||
$level = get_value($name,'smLevel',1);
|
||||
$events = explode('|',get_value($disk,'smEvents',$numbers));
|
||||
$title = '';
|
||||
$thumb = 'thumbs-o-up';
|
||||
$text = 'healthy';
|
||||
$color = 'green';
|
||||
$file = "state/smart/$name";
|
||||
if (file_exists("$file.ssa") && in_array(file_get_contents("$file.ssa"),$failed)) {
|
||||
$title = "S.M.A.R.T health-check failed\n"; $thumb = 'thumbs-o-down'; $color = 'red'; $text = 'fail'; $fail++;
|
||||
} else {
|
||||
if (empty($saved["smart"]["$name.ack"])) {
|
||||
exec("awk 'NR>7{print $1,$2,$4,$6,$9,$10}' ".escapeshellarg($file)." 2>/dev/null", $codes);
|
||||
foreach ($codes as $code) {
|
||||
if (!$code || !is_numeric($code[0])) continue;
|
||||
list($id,$class,$value,$thres,$when,$raw) = explode(' ',$code);
|
||||
$failing = strpos($when,'FAILING_NOW')!==false;
|
||||
if (!$failing && !in_array($id,$events)) continue;
|
||||
if ($failing || ($select ? $thres>0 && $value<=$thres*$level : $raw>0)) $title .= normalize($class,$failing?$when:$raw);
|
||||
}
|
||||
if ($title) {$thumb = 'thumbs-o-down'; $color = 'orange'; $text = 'error'; $smart++;} else $title = "No errors reported\n";
|
||||
}
|
||||
}
|
||||
$title .= "Click for context menu";
|
||||
return "<span id='smart-$name' name='$page' class='fa fa-$thumb $color-text' style='margin-right:8px' onmouseover='this.style.cursor=\"pointer\"' title='$title'></span>$text";
|
||||
}
|
||||
function device_usage(&$disk, $array, &$full, &$high) {
|
||||
if ($array) {
|
||||
$text = $_POST['text'];
|
||||
$used = ($disk['type']!='Parity' && $disk['fsStatus']=='Mounted') ? (($disk['fsSize'] ? round((1-$disk['fsFree']/$disk['fsSize'])*100):0).'%') : false;
|
||||
if ($used && ($text==2 || $text==21)) {
|
||||
$load = substr($used,0,-1);
|
||||
$critical = $disk['critical'] ?? $_POST['critical'];
|
||||
$warning = $disk['warning'] ?? $_POST['warning'];
|
||||
if ($load >= $critical) {$class = 'redbar'; $full++;}
|
||||
elseif ($load >= $warning) {$class = 'orangebar'; $high++;}
|
||||
else $class = 'greenbar';
|
||||
} else $class = false;
|
||||
} else $used = false;
|
||||
if ($used) {
|
||||
return $text%10==0 ? $used : "<span class='load'>$used</span><div class='usage-disk sys'><span style='width:$used'".($class?" class='$class'":"")."></span></div>";
|
||||
} else {
|
||||
return $text%10==0 ? "-" : "<span class='load'>-</span><div class='usage-disk sys none'></div>";
|
||||
}
|
||||
}
|
||||
function array_group($type) {
|
||||
global $disks,$error,$warning,$red,$orange,$fail,$smart,$full,$high;
|
||||
foreach ($disks as $disk) if ($disk['type']==$type && strpos($disk['status'],'DISK_NP')===false) {
|
||||
echo "<tr><td></td>";
|
||||
echo "<td>".device_name($disk,true)."</td>";
|
||||
echo "<td>".device_status($disk,$error,$warning)."</td>";
|
||||
echo "<td>".device_temp($disk,$red,$orange)."</td>";
|
||||
echo "<td>".device_smart($disk,false,$fail,$smart)."</td>";
|
||||
echo "<td>".device_usage($disk,true,$full,$high)."</td>";
|
||||
echo "<td></td></tr>";
|
||||
}
|
||||
}
|
||||
function extra_group(&$disks) {
|
||||
global $disks,$error,$warning,$red,$orange,$fail,$smart,$full,$high;
|
||||
foreach ($disks as $disk) {
|
||||
$name = $disk['device'];
|
||||
$port = port_name($name);
|
||||
$smart = "state/smart/$name";
|
||||
$disk['color'] = exec("hdparm -C /dev/$port|grep -Po 'active|unknown'") ? 'blue-on' : 'blue-blink';
|
||||
$disk['temp'] = file_exists($smart) ? exec("awk 'BEGIN{s=t=\"*\"}\$1==190{s=\$10};\$1==194{t=\$10;exit};\$1==\"Temperature:\"{t=\$2;exit};/^Current Drive Temperature:/{t=\$4;exit} END{if(t!=\"*\")print t; else print s}' $smart") : '*';
|
||||
echo "<tr><td></td>";
|
||||
echo "<td>".device_name($disk,false)."</td>";
|
||||
echo "<td>".device_status($disk,$error,$warning)."</td>";
|
||||
echo "<td>".device_temp($disk,$red,$orange)."</td>";
|
||||
echo "<td>".device_smart($disk,$name,$fail,$smart)."</td>";
|
||||
echo "<td>".device_usage($disk,false,$full,$high)."</td>";
|
||||
echo "<td></td></tr>";
|
||||
}
|
||||
}
|
||||
switch ($_POST['cmd']) {
|
||||
case 'disk':
|
||||
$i = 1;
|
||||
case 'array':
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$disks = array_filter(parse_ini_file('state/disks.ini',true),'active_disks');
|
||||
$saved = @parse_ini_file('state/monitor.ini',true) ?: [];
|
||||
require_once "$docroot/webGui/include/CustomMerge.php";
|
||||
require_once "$docroot/webGui/include/Preselect.php";
|
||||
$error = $warning = $red = $orange = $fail = $smart = $full = $high = 0;
|
||||
array_group('Parity');
|
||||
array_group('Data');
|
||||
echo "\0".($error+$warning)."\0".($red+$orange)."\0".($fail+$smart)."\0".($full+$high);
|
||||
break;
|
||||
case 'cache':
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$disks = array_filter(parse_ini_file('state/disks.ini',true),'active_disks');
|
||||
$saved = @parse_ini_file('state/monitor.ini',true) ?: [];
|
||||
require_once "$docroot/webGui/include/CustomMerge.php";
|
||||
require_once "$docroot/webGui/include/Preselect.php";
|
||||
$error = $warning = $red = $orange = $fail = $smart = $full = $high = 0;
|
||||
array_group('Cache');
|
||||
echo "\0".($error+$warning)."\0".($red+$orange)."\0".($fail+$smart)."\0".($full+$high);
|
||||
break;
|
||||
case 'extra':
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$devs = parse_ini_file('state/devs.ini',true);
|
||||
$saved = @parse_ini_file('state/monitor.ini',true) ?: [];
|
||||
require_once "$docroot/webGui/include/CustomMerge.php";
|
||||
require_once "$docroot/webGui/include/Preselect.php";
|
||||
$slots = $_POST['slots'];
|
||||
$row1 = array_fill(0,31,'<td></td>'); my_insert($row1[0],'Encrypted');
|
||||
$row2 = array_fill(0,31,'<td></td>'); my_insert($row2[0],'Active');
|
||||
$row3 = array_fill(0,31,'<td></td>'); my_insert($row3[0],'Inactive');
|
||||
$row4 = array_fill(0,31,'<td></td>'); my_insert($row4[0],'Unassigned');
|
||||
$row5 = array_fill(0,31,'<td></td>'); my_insert($row5[0],'Faulty');
|
||||
$row6 = array_fill(0,31,'<td></td>'); my_insert($row6[0],'Heat alarm');
|
||||
$row7 = array_fill(0,31,'<td></td>'); my_insert($row7[0],'SMART status');
|
||||
$row8 = array_fill(0,31,'<td></td>'); my_insert($row8[0],'Utilization');
|
||||
$diskRow = function($n,$disk) use (&$row1,&$row2,&$row3,&$row4,&$row5,&$row6,&$row7,&$row8,$path,$var) {
|
||||
if ($n>0) {
|
||||
if (isset($disk['luksState'])) {
|
||||
switch ($disk['luksState']) {
|
||||
case 0: $luks = strpos($disk['fsType'],'luks:')===false ? "" : "<i class='fa fa-unlock orange-text'></i>"; break;
|
||||
case 1: if ($var['fsState']!='Stopped') {$luks = "<i class='fa fa-unlock-alt green-text'></i>"; break;}
|
||||
case 2: $luks = "<i class='fa fa-lock green-text'></i>"; break;
|
||||
case 3: $luks = "<i class='fa fa-lock red-text'></i>"; break;
|
||||
default: $luks = "<i class='fa fa-lock red-text'></i>"; break;
|
||||
}
|
||||
} else $luks = "";
|
||||
my_insert($row1[$n],$luks);
|
||||
$state = $disk['color'];
|
||||
switch ($state) {
|
||||
case 'grey-off':
|
||||
break; //ignore
|
||||
case 'green-on':
|
||||
my_insert($row2[$n],"<img src=$path/$state.png>");
|
||||
break;
|
||||
case 'green-blink':
|
||||
my_insert($row3[$n],"<img src=$path/$state.png>");
|
||||
break;
|
||||
case 'blue-on':
|
||||
case 'blue-blink':
|
||||
my_insert($row4[$n],"<img src=$path/$state.png>");
|
||||
break;
|
||||
default:
|
||||
my_insert($row5[$n],"<img src=$path/$state.png>");
|
||||
break;}
|
||||
$temp = $disk['temp'];
|
||||
$hot = $disk['hotTemp'] ?? $_POST['hot'];
|
||||
$max = $disk['maxTemp'] ?? $_POST['max'];
|
||||
$top = $_POST['top'] ?? 120;
|
||||
$heat = exceed($temp,$max,$top) ? 'max' : (exceed($temp,$hot,$top) ? 'hot' : '');
|
||||
if ($heat)
|
||||
my_insert($row6[$n],"<span class='heat-img'><img src='$path/$heat.png'></span><span class='heat-text' style='display:none'>".my_temp($temp,$_POST['unit'])."</span>");
|
||||
else
|
||||
if (!strpos($state,'blink') && $temp>0) my_insert($row6[$n],"<span class='temp-text'>".my_temp($temp,$_POST['unit'])."</span>");
|
||||
if ($disk['device'] && !strpos($state,'blink')) my_smart($row7[$n],$disk['name'],'Device');
|
||||
my_usage($row8[$n],($disk['type']!='Parity' && $disk['fsStatus']=='Mounted')?(($disk['fsSize'] ? round((1-$disk['fsFree']/$disk['fsSize'])*100):0).'%'):'',$disk);
|
||||
}
|
||||
};
|
||||
$devRow = function($n,$disk) use (&$row4,&$row6,&$row7,$path) {
|
||||
$hot = $_POST['hot'];
|
||||
$max = $_POST['max'];
|
||||
$top = $_POST['top'] ?? 120;
|
||||
$name = $disk['device'];
|
||||
$port = substr($name,-2)!='n1' ? $name : substr($name,0,-2);
|
||||
$smart = "state/smart/$name";
|
||||
$state = exec("hdparm -C ".escapeshellarg("/dev/$port")."|grep -Po 'active|unknown'") ? 'blue-on' : 'blue-blink';
|
||||
if ($state=='blue-on') my_smart($row7[$n],$name,'New');
|
||||
$temp = file_exists($smart) ? exec("awk 'BEGIN{s=t=\"*\"}\$1==190{s=\$10};\$1==194{t=\$10;exit};\$1==\"Temperature:\"{t=\$2;exit};/^Current Drive Temperature:/{t=\$4;exit} END{if(t!=\"*\")print t; else print s}' ".escapeshellarg($smart)) : '*';
|
||||
$heat = exceed($temp,$max,$top) ? 'max' : (exceed($temp,$hot,$top) ? 'hot' : '');
|
||||
if ($heat)
|
||||
my_insert($row6[$n],"<span class='heat-img'><img src='$path/$heat.png'></span><span class='heat-text' style='display:none'>".my_temp($temp,$_POST['unit'])."</span>");
|
||||
else
|
||||
if ($state=='blue-on' && $temp>0) my_insert($row6[$n],"<span class='temp-text'>".my_temp($temp,$_POST['unit'])."</span>");
|
||||
my_insert($row4[$n],"<img src=$path/$state.png>");
|
||||
};
|
||||
foreach ($disks as $disk) if ($disk['type']=='Parity') $diskRow($i++,$disk);
|
||||
foreach ($disks as $disk) if ($disk['type']=='Data') $diskRow($i++,$disk);
|
||||
if ($slots <= 30) {
|
||||
foreach ($disks as $disk) if ($disk['type']=='Cache') $diskRow($i++,$disk);
|
||||
foreach ($devs as $dev) $devRow($i++,$dev);
|
||||
}
|
||||
echo "<tr>".implode('',$row1)."</tr>";
|
||||
echo "<tr>".implode('',$row2)."</tr>";
|
||||
echo "<tr>".implode('',$row3)."</tr>";
|
||||
echo "<tr>".implode('',$row4)."</tr>";
|
||||
echo "<tr>".implode('',$row5)."</tr>";
|
||||
echo "<tr>".implode('',$row6)."</tr>";
|
||||
echo "<tr>".implode('',$row7)."</tr>";
|
||||
echo "<tr>".implode('',$row8)."</tr>";
|
||||
if ($slots > 30) {
|
||||
echo '#'; $i = 1;
|
||||
$row1 = array_fill(0,31,'<td></td>'); my_insert($row1[0],'Encrypted');
|
||||
$row2 = array_fill(0,31,'<td></td>'); my_insert($row2[0],'Active');
|
||||
$row3 = array_fill(0,31,'<td></td>'); my_insert($row3[0],'Inactive');
|
||||
$row4 = array_fill(0,31,'<td></td>'); my_insert($row4[0],'Unassigned');
|
||||
$row5 = array_fill(0,31,'<td></td>'); my_insert($row5[0],'Faulty');
|
||||
$row6 = array_fill(0,31,'<td></td>'); my_insert($row6[0],'Heat alarm');
|
||||
$row7 = array_fill(0,31,'<td></td>'); my_insert($row7[0],'SMART status');
|
||||
$row8 = array_fill(0,31,'<td></td>'); my_insert($row8[0],'Utilization');
|
||||
foreach ($disks as $disk) if ($disk['type']=='Cache') $diskRow($i++,$disk);
|
||||
foreach ($devs as $dev) $devRow($i++,$dev);
|
||||
echo "<tr>".implode('',$row1)."</tr>";
|
||||
echo "<tr>".implode('',$row2)."</tr>";
|
||||
echo "<tr>".implode('',$row3)."</tr>";
|
||||
echo "<tr>".implode('',$row4)."</tr>";
|
||||
echo "<tr>".implode('',$row5)."</tr>";
|
||||
echo "<tr>".implode('',$row6)."</tr>";
|
||||
echo "<tr>".implode('',$row7)."</tr>";
|
||||
echo "<tr>".implode('',$row8)."</tr>";
|
||||
}
|
||||
break;
|
||||
$error = $warning = $red = $orange = $fail = $smart = $full = $high = 0;
|
||||
extra_group($devs);
|
||||
echo "\0".($error+$warning)."\0".($red+$orange)."\0".($fail+$smart)."\0".($full+$high);
|
||||
break;
|
||||
case 'sys':
|
||||
exec("grep -Po '^Mem(Total|Available):\s+\K\d+' /proc/meminfo",$memory);
|
||||
exec("df /boot /var/log /var/lib/docker|grep -Po '\d+%'",$sys);
|
||||
$mem = max(round((1-$memory[1]/$memory[0])*100),0);
|
||||
echo "{$mem}%#".implode('#',$sys);
|
||||
break;
|
||||
echo "{$mem}%\0".implode("\0",$sys);
|
||||
break;
|
||||
case 'fan':
|
||||
exec("sensors -uA 2>/dev/null|grep -Po 'fan\d_input: \K\d+'",$rpms);
|
||||
if ($rpms) echo implode(' RPM#',$rpms).' RPM';
|
||||
break;
|
||||
if ($rpms) echo implode(" RPM\0",$rpms).' RPM';
|
||||
break;
|
||||
case 'port':
|
||||
$i = 0;
|
||||
$ports = explode(',',$_POST['ports']);
|
||||
switch ($_POST['view']) {
|
||||
case 'main':
|
||||
$ports = explode(',',$_POST['ports']); $i = 0;
|
||||
foreach ($ports as $port) {
|
||||
$mtu = file_get_contents("/sys/class/net/$port/mtu");
|
||||
$int = "/sys/class/net/$port";
|
||||
$mtu = file_get_contents("$int/mtu");
|
||||
$link = file_get_contents("$int/carrier")==1;
|
||||
if (substr($port,0,4)=='bond') {
|
||||
$ports[$i++] = exec("grep -Pom1 '^Bonding Mode: \K.+' ".escapeshellarg("/proc/net/bonding/$port")).", mtu $mtu";
|
||||
if ($link) {
|
||||
$bond_mode = str_replace('Bonding Mode: ','',file("/proc/net/bonding/$port",FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)[1]);
|
||||
$ports[$i++] = "$bond_mode, mtu $mtu";
|
||||
} else $ports[$i++] = "bond down";
|
||||
} elseif ($port=='lo') {
|
||||
$ports[$i++] = str_replace('yes','loopback',exec("ethtool lo|grep -Pom1 '^\s+Link detected: \K.+'"));
|
||||
$ports[$i++] = $link ? "loopback" : "not set";
|
||||
} else {
|
||||
unset($info);
|
||||
exec("ethtool ".escapeshellarg($port)."|grep -Po '^\s+(Speed|Duplex|Link\sdetected): \K[^U\\n]+'",$info);
|
||||
$ports[$i++] = (array_pop($info)=='yes' && $info[0]) ? str_replace(['M','G'],[' M',' G'],$info[0]).", ".strtolower($info[1])." duplex, mtu $mtu" : "not connected";
|
||||
if ($link) {
|
||||
$speed = file_get_contents("$int/speed");
|
||||
$duplex = file_get_contents("$int/duplex");
|
||||
$ports[$i++] = "$speed Mbps, $duplex duplex, mtu $mtu";
|
||||
} else $ports[$i++] = "interface down";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'port':
|
||||
foreach ($ports as $port) {
|
||||
$int = "/sys/class/net/$port";
|
||||
$rx_bytes = file_get_contents("$int/statistics/rx_bytes");
|
||||
$tx_bytes = file_get_contents("$int/statistics/tx_bytes");
|
||||
$ports[$i++] = "{$rx_bytes}\0{$tx_bytes}";
|
||||
}
|
||||
break;
|
||||
case 'link':
|
||||
foreach ($ports as $port) {
|
||||
$int = "/sys/class/net/$port";
|
||||
$rx_errors = file_get_contents("$int/statistics/rx_errors");
|
||||
$rx_drops = file_get_contents("$int/statistics/rx_dropped");
|
||||
$rx_fifo = file_get_contents("$int/statistics/rx_fifo_errors");
|
||||
$tx_errors = file_get_contents("$int/statistics/tx_errors");
|
||||
$tx_drops = file_get_contents("$int/statistics/tx_dropped");
|
||||
$tx_fifo = file_get_contents("$int/statistics/tx_fifo_errors");
|
||||
$ports[$i++] = "Errors: {$rx_errors}<br>Drops: {$rx_drops}<br>Overruns: {$rx_fifo}\0Errors: {$tx_errors}<br>Drops: {$tx_drops}<br>Overruns: {$tx_fifo}";
|
||||
}
|
||||
break;
|
||||
}
|
||||
echo implode("\0",$ports);
|
||||
break;
|
||||
case 'port': exec("ifconfig -a -s|awk '/^(bond|eth|lo)[0-9]*\s/{print $3\"#\"$7}'",$ports); break;
|
||||
case 'link': exec("ifconfig -a -s|awk '/^(bond|eth|lo)[0-9]*\s/{print \"Errors: \"$4\"<br>Drops: \"$5\"<br>Overruns: \"$6\"#Errors: \"$8\"<br>Drops: \"$9\"<br>Overruns: \"$10}'",$ports); break;
|
||||
default: $ports = [];}
|
||||
echo implode('#',$ports);
|
||||
break;
|
||||
case 'parity':
|
||||
$var = parse_ini_file("state/var.ini");
|
||||
if ($var['mdResync']>0) {
|
||||
case 'speed':
|
||||
$i = 0;
|
||||
$ports = explode(',',$_POST['ports']);
|
||||
foreach ($ports as $port) {
|
||||
if ($port=='bond0' || $port=='eth0') {
|
||||
$int = "/sys/class/net/$port";
|
||||
$rx_new = (float)file_get_contents("$int/statistics/rx_bytes");
|
||||
$tx_new = (float)file_get_contents("$int/statistics/tx_bytes");
|
||||
break;;
|
||||
}
|
||||
}
|
||||
$time_new = microtime(true);
|
||||
$time_old = (float)$_POST['timestamp'];
|
||||
$rx_old = (float)$_POST['rx_bytes'];
|
||||
$tx_old = (float)$_POST['tx_bytes'];
|
||||
if ($time_old) {
|
||||
$rx_speed = my_scale(($rx_new-$rx_old)/($time_new-$time_old)*8,$unit,1,-1).' '.str_replace('B','b',$unit).'ps';
|
||||
$tx_speed = my_scale(($tx_new-$tx_old)/($time_new-$time_old)*8,$unit,1,-1).' '.str_replace('B','b',$unit).'ps';
|
||||
} else $rx_speed = $tx_speed = '---';
|
||||
echo "$rx_speed\0$tx_speed\0$time_new\0$rx_new\0$tx_new";
|
||||
break;
|
||||
case 'status':
|
||||
$var = parse_ini_file("state/var.ini");
|
||||
$disks = array_filter(parse_ini_file('state/disks.ini',true),'parity_disks');
|
||||
$parity_slots = count($disks);
|
||||
$parity_disabled = $parity_invalid = 0;
|
||||
foreach ($disks as $disk) {
|
||||
if (strpos($disk['status'],"DISK_NP")===0) $parity_disabled++;
|
||||
elseif (strpos($disk['status'],"DISK_INVALID")===0) $parity_invalid++;
|
||||
}
|
||||
if ($var['mdResync']==0) {
|
||||
if ($parity_slots==$parity_disabled) {
|
||||
echo "<span class='red'>Parity disk".($parity_slots==1?'':'s')." not present</span>";
|
||||
} elseif ($parity_slots > $parity_invalid) {
|
||||
if ($parity_invalid==0) {
|
||||
echo "<span class='green'>Parity is valid</span>";
|
||||
} else {
|
||||
echo "<span class='orange'>Parity is degraded: $parity_invalid invalid device".($parity_invalid==1?'':'s')."</span>";
|
||||
}
|
||||
} else {
|
||||
if (empty($var['mdInvalidDisk'])) {
|
||||
echo "<span class='red strong'>Parity is invalid</span>";
|
||||
} else {
|
||||
echo "<span class='red strong'>Data is invalid</span>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$mode = '';
|
||||
$number = $_POST['number'] ?? '.,';
|
||||
if (strstr($var['mdResyncAction'],"recon")) {
|
||||
$mode = 'Parity-Sync / Data-Rebuild';
|
||||
$mode = 'Parity-Sync/Data-Rebuild';
|
||||
} elseif (strstr($var['mdResyncAction'],"clear")) {
|
||||
$mode = 'Clearing';
|
||||
} elseif ($var['mdResyncAction']=="check") {
|
||||
@@ -316,9 +386,49 @@ case 'parity':
|
||||
} elseif (strstr($var['mdResyncAction'],"check")) {
|
||||
$mode = 'Parity-Check';
|
||||
}
|
||||
echo "<span class='orange p0'><strong>".$mode." in progress... Completed: ".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),0)." %.</strong></span>";
|
||||
echo "<br><i class='fa fa-clock-o'></i> <em>Elapsed time: ".my_clock(floor((time()-$var['sbUpdated'])/60)).". Estimated finish: ".my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0))."</em>";
|
||||
echo "<span class='orange'>$mode in progress... Completed: ".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),1,$number[0],$number[1])." %.</span>";
|
||||
}
|
||||
break;
|
||||
case 'parity':
|
||||
$var = parse_ini_file("state/var.ini");
|
||||
$time = $_POST['time'];
|
||||
$idle = $var['mdResync']==0;
|
||||
if ($var['sbSyncExit']!=0) {
|
||||
echo "Last check incomplete on <strong>".my_time($var['sbSynced2'],$time).day_count($var['sbSynced2'])."</strong>, finding <strong>{$var['sbSyncErrs']}</strong> error".($var['sbSyncErrs']==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-dot-circle-o'></i> Error code: ".my_error($var['sbSyncExit']);
|
||||
} elseif ($var['sbSynced']==0) {
|
||||
list($date,$duration,$speed,$status,$error) = last_parity_log();
|
||||
if (!$date) {
|
||||
echo "Parity has not been checked yet.";
|
||||
} elseif ($status==0) {
|
||||
echo "Last checked on <strong>".my_time($date).day_count($date,$time)."</strong>, finding <strong>$error</strong> error".($error==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-clock-o'></i> Duration: ".my_check($duration,$speed);
|
||||
} else {
|
||||
echo "Last check incomplete on <strong>".my_time($date,$time).day_count($date)."</strong>, finding <strong>$error</strong> error".($error==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-dot-circle-o'></i> Error code: ".my_error($status);
|
||||
}
|
||||
} elseif ($var['sbSynced2']==0) {
|
||||
if ($idle) {
|
||||
list($entry,$duration,$speed,$status,$error) = explode('|', read_parity_log($var['sbSynced'],!$idle));
|
||||
if ($status==0) {
|
||||
echo "Last checked on <strong>".my_time($var['sbSynced'],$time).day_count($var['sbSynced'])."</strong>, finding <strong>$error</strong> error".($error==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-clock-o'></i> Duration: ".my_check($duration,$speed);
|
||||
} else {
|
||||
echo "Last check incomplete on <strong>".my_time($var['sbSynced'],$time).day_count($var['sbSynced'])."</strong>, finding <strong>$error</strong> error".($error==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-dot-circle-o'></i> Error code: ".my_error($status);
|
||||
}
|
||||
} else {
|
||||
echo "Activity started on <strong>".my_time($var['sbSynced'],$time).day_count($var['sbSynced'])."</strong>, finding <span id='errors'><strong>{$var['sbSyncErrs']}</strong> error".($var['sbSyncErrs']==1?'.':'s.')."</span>";
|
||||
echo "<br><i class='fa fa-clock-o'></i> Elapsed time: ".my_clock(floor((time()-$var['sbUpdated'])/60))."<span class='finish'><i class='fa fa-flag-checkered'></i> Estimated finish: ".my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0))."</span>";
|
||||
}
|
||||
} else {
|
||||
$status = 0;
|
||||
$duration = $var['sbSynced2']-$var['sbSynced'];
|
||||
$speed = $duration?my_scale($var['mdResyncSize']*1024/$duration,$unit,1)." $unit/sec":'';
|
||||
echo "Last checked on <strong>".my_time($var['sbSynced2'],$time).day_count($var['sbSynced2'])."</strong>, finding <strong>{$var['sbSyncErrs']}</strong> error".($var['sbSyncErrs']==1?'.':'s.');
|
||||
echo "<br><i class='fa fa-clock-o'></i> Duration: ".my_check($duration,$speed);
|
||||
}
|
||||
if ($idle) {
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
list($m,$h) = explode(' ', $parity['hour']);
|
||||
$time = time();
|
||||
@@ -381,24 +491,24 @@ case 'parity':
|
||||
case 'WL': $t = stage(0); break;}
|
||||
break;
|
||||
}
|
||||
echo "\0";
|
||||
echo "Next check scheduled on <strong>";
|
||||
echo strftime($_POST['time'],$time+$t);
|
||||
echo "</strong><br><i class='fa fa-clock-o'></i> <em>Due in: ";
|
||||
echo "</strong><br><i class='fa fa-clock-o'></i> Due in: ";
|
||||
echo my_clock(floor($t/60));
|
||||
echo "</em>";
|
||||
} else {
|
||||
echo "\0";
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 'shares':
|
||||
$names = explode(',',$_POST['names']);
|
||||
switch ($_POST['com']) {
|
||||
case 'smb':
|
||||
exec("lsof /mnt/user /mnt/disk* 2>/dev/null|awk '/^smbd/ && $0!~/\.AppleD(B|ouble)/ && $5==\"REG\"'|awk -F/ '{print $4}'",$lsof);
|
||||
$counts = array_count_values($lsof); $count = [];
|
||||
foreach ($names as $name) $count[] = $counts[$name] ?? 0;
|
||||
echo implode('#',$count);
|
||||
break;
|
||||
case 'afp':
|
||||
case 'nfs':
|
||||
// not available
|
||||
break;}
|
||||
break;}
|
||||
$names = explode(',',$_POST['names']);
|
||||
switch ($_POST['com']) {
|
||||
case 'smb':
|
||||
exec("LANG='en_US.UTF8' lsof -Owl /mnt/disk[0-9]* 2>/dev/null|awk '/^shfs/ && \$0!~/\.AppleD(B|ouble)/ && \$5==\"REG\"'|awk -F/ '{print \$4}'",$lsof);
|
||||
$counts = array_count_values($lsof); $count = [];
|
||||
foreach ($names as $name) $count[] = $counts[$name] ?? 0;
|
||||
echo implode("\0",$count);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user