mirror of
https://github.com/unraid/webgui.git
synced 2026-04-30 14:59:22 -05:00
merge ronalds changes from upstream + some vm and dashboard fixes
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Bergware International.
|
||||
* Copyright 2015, Lime Technology
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$ram = "/var/local/emhttp/monitor.ini";
|
||||
$rom = "/boot/config/plugins/dynamix/monitor.ini";
|
||||
$saved = parse_ini_file($ram,true);
|
||||
$saved["smart"]["{$_POST['disk']}.ack"] = "true";
|
||||
|
||||
$text = "";
|
||||
foreach ($saved as $item => $block) {
|
||||
if ($block) $text .= "[$item]\n";
|
||||
foreach ($block as $key => $value) $text .= "$key=\"$value\"\n";
|
||||
}
|
||||
file_put_contents($ram, $text);
|
||||
file_put_contents($rom, $text);
|
||||
echo "200 OK";
|
||||
?>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
// Color coding for syslog and disk log
|
||||
$match =
|
||||
[['class' => 'text',
|
||||
'text' => ['to the standard error','non[ -]fatal error','correct gpt errors','error handler\b','(kernel|logger): [|+ #-.]','logger: (naming|log)']
|
||||
],
|
||||
['class' => 'login',
|
||||
'text' => ['(accepted|failed) password','sshd\[\d+\]:']
|
||||
],
|
||||
['class' => 'warn',
|
||||
'text' => ['\b(warning|conflicts|kill|failed|checksum|spurious|replayed|preclear_disk)\b','acpi (error|exception)','\b(soft|hard) resetting ','\<errno=[^0]','host protected area','invalid signature','limiting speed to','duplicate (object|error)\b','power is back','gpt:partition_entry','no floppy controller']
|
||||
],
|
||||
['class' => 'error',
|
||||
'text' => ['\b(error|emask|tainted|killed|fsck\?|parity incorrect|invalid opcode|kernel bug|power failure)\b','\b(dma|ata\d+[.:]) disabled','nobody cared','unknown boot option','write protect is on','call trace','out[ _]of[ _]memory','hpa detected: current \d+']
|
||||
],
|
||||
['class' => 'system',
|
||||
'text' => ['\b(checksumming|controller|driver|version|highmem|lowmem|bogomips)\b','throttling rate','get value of subfeature','[mg]hz processor','cpu\d*: (intel|amd)','kernel: (processors|memory|smp|console):','\bmd: xor using','thermal zone','adding \d+k swap on','kernel command line:','_sse','found.*chip','\b(mouse|speaker|kbd port|aux port|ps\/2|keyboard)\b']
|
||||
],
|
||||
['class' => 'array',
|
||||
'text' => [': (mdcmd|md|super\.dat|unraid system|unregistered|running, size)\b','key detected, registered']
|
||||
]
|
||||
];
|
||||
?>
|
||||
@@ -0,0 +1,18 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
// Merge SMART settings
|
||||
$smartONE = '/boot/config/smart-one.cfg';
|
||||
$smartALL = '/boot/config/smart-all.cfg';
|
||||
if (file_exists($smartONE)) $disks = array_merge_recursive($disks, parse_ini_file($smartONE,true));
|
||||
if (file_exists($smartALL)) $var = array_merge($var, parse_ini_file($smartALL));
|
||||
?>
|
||||
@@ -11,20 +11,37 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$path = '/webGui/images';
|
||||
|
||||
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) {
|
||||
global $path;
|
||||
function my_smart(&$source,$name,$page) {
|
||||
global $var,$disks,$path,$failed,$numbers,$saved;
|
||||
$disk = &$disks[$name];
|
||||
$select = isset($disk['smSelect']) ? $disk['smSelect'] : -1; if ($select==-1) $select = isset($var['smSelect']) ? $var['smSelect'] : 0;
|
||||
$level = isset($disk['smLevel']) ? $disk['smLevel'] : -1; if ($level==-1) $level = isset($var['smLevel']) ? $var['smLevel'] : 1;
|
||||
$events = isset($disk['smEvents']) ? explode('|',$disk['smEvents']) : (isset($var['smEvents']) ? explode('|',$var['smEvents']) : $numbers);
|
||||
$thumb = 'good';
|
||||
$saved = @parse_ini_file("/var/local/emhttp/monitor.ini",true);
|
||||
$last = isset($saved["smart"]["$name.5"]) ? $saved["smart"]["$name.5"] : 0;
|
||||
$smart = exec("grep -Pom1 '^ 5.+ \K\d+$' /var/local/emhttp/smart/$name");
|
||||
if (!$smart) $smart = 0;
|
||||
if (($last == 0 && $smart > 0) || ($last > 0 && $smart > $last)) $thumb = 'bad';
|
||||
my_insert($source, "<a href=\"/Main/Device?name=$name\" onclick=\"$.cookie('one','tab2',{path:'/'})\" title=\"$smart reallocated sectors\"><img src=\"$path/$thumb.png\"></a>");
|
||||
$file = "state/smart/$name";
|
||||
if (file_exists("$file.ssa") && in_array(file_get_contents("$file.ssa"),$failed)) {
|
||||
$thumb = 'bad';
|
||||
} else {
|
||||
if (empty($saved["smart"]["$name.ack"])) {
|
||||
exec("awk 'NR>7{print $1,$2,$4,$6,$9,$10}' $file 2>/dev/null", $codes);
|
||||
foreach ($codes as $code) {
|
||||
if (!$code) 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)) {$thumb = 'alert'; break;};
|
||||
}
|
||||
}
|
||||
}
|
||||
my_insert($source, "<span id='smart-$name' name='$page' class='$thumb'><img src=\"$path/$thumb.png\" onmouseover=\"this.style.cursor='pointer'\" title=\"Click to get context menu\"></span>");
|
||||
}
|
||||
function my_usage(&$source,$used) {
|
||||
my_insert($source, $used ? "<div class='usage-disk all'><span style='width:$used'>$used</span></div>" : "-");
|
||||
@@ -48,33 +65,28 @@ function mhz($speed) {
|
||||
function rpm($speed) {
|
||||
return "$speed RPM";
|
||||
}
|
||||
$path = '/webGui/images';
|
||||
$failed = ['FAILED','NOK'];
|
||||
switch ($_POST['cmd']) {
|
||||
case 'disk':
|
||||
$i = 2;
|
||||
$disks = parse_ini_file("state/disks.ini",true);
|
||||
$devs = parse_ini_file("state/devs.ini",true);
|
||||
$row1 = array_fill(0,26,"<td></td>"); my_insert($row1[0],"Active");
|
||||
$row2 = array_fill(0,26,"<td></td>"); my_insert($row2[0],"Inactive");
|
||||
$row3 = array_fill(0,26,"<td></td>"); my_insert($row3[0],"Unassigned");
|
||||
$row4 = array_fill(0,26,"<td></td>"); my_insert($row4[0],"Faulty");
|
||||
$row5 = array_fill(0,26,"<td></td>"); my_insert($row5[0],"Heat alarm");
|
||||
$row6 = array_fill(0,26,"<td></td>"); my_insert($row6[0],"SMART status");
|
||||
$row7 = array_fill(0,26,"<td></td>"); my_insert($row7[0],"Utilization");
|
||||
foreach ($disks as $disk) {
|
||||
$state = $disk['color'];
|
||||
$n = 0;
|
||||
switch ($disk['type']) {
|
||||
case 'Parity':
|
||||
if ($disk['status']!='DISK_NP') $n = 1;
|
||||
break;
|
||||
case 'Data':
|
||||
if ($disk['status']!='DISK_NP') $n = $i++;
|
||||
break;
|
||||
case 'Cache':
|
||||
if ($disk['status']!='DISK_NP') $n = $i++;
|
||||
if ($disk['name']!='cache') $disk['fsStatus']=='-';
|
||||
break;}
|
||||
$i = 1;
|
||||
$var = [];
|
||||
$disks = @parse_ini_file('state/disks.ini',true);
|
||||
$devs = @parse_ini_file('state/devs.ini',true);
|
||||
$saved = @parse_ini_file('state/monitor.ini',true);
|
||||
require_once 'CustomMerge.php';
|
||||
require_once 'Preselect.php';
|
||||
$slots = max(count($disks)+count($devs)-1, 25)+1;
|
||||
$row1 = array_fill(0,$slots,'<td></td>'); my_insert($row1[0],'Active');
|
||||
$row2 = array_fill(0,$slots,'<td></td>'); my_insert($row2[0],'Inactive');
|
||||
$row3 = array_fill(0,$slots,'<td></td>'); my_insert($row3[0],'Unassigned');
|
||||
$row4 = array_fill(0,$slots,'<td></td>'); my_insert($row4[0],'Faulty');
|
||||
$row5 = array_fill(0,$slots,'<td></td>'); my_insert($row5[0],'Heat alarm');
|
||||
$row6 = array_fill(0,$slots,'<td></td>'); my_insert($row6[0],'SMART status');
|
||||
$row7 = array_fill(0,$slots,'<td></td>'); my_insert($row7[0],'Utilization');
|
||||
$funcRenderRow = function($n,$disk) use (&$row1,&$row2,&$row3,&$row4,&$row5,&$row6,&$row7,$path,$_POST) {
|
||||
if ($n>0) {
|
||||
$state = $disk['color'];
|
||||
switch ($state) {
|
||||
case 'grey-off':
|
||||
break; //ignore
|
||||
@@ -89,15 +101,34 @@ case 'disk':
|
||||
my_insert($row3[$n],"<img src=$path/$state.png>");
|
||||
break;
|
||||
default:
|
||||
my_insert($row4[$n],"<img src=$path/$state.png>");
|
||||
if ($disk['type']=='Parity' && $disk['status']=='DISK_NP_DSBL')
|
||||
my_insert($row3[$n],"<img src=$path/$state.png>"); //parity is really unassigned
|
||||
else
|
||||
my_insert($row4[$n],"<img src=$path/$state.png>");
|
||||
break;}
|
||||
$temp = $disk['temp'];
|
||||
if ($temp>=$_POST['hot']) my_insert($row5[$n],"<span class='heat-img'><img src='$path/".($temp>=$_POST['max']?'max':'hot').".png'></span><span class='heat-text' style='display:none'>".my_temp($temp,$_POST['unit'])."</span>");
|
||||
if ($disk['device'] && !strpos($state,'blink')) my_smart($row6[$n],$disk['name']);
|
||||
my_usage($row7[$n],($n>1 && $disk['fsStatus']=='Mounted')?(round((1-$disk['fsFree']/$disk['fsSize'])*100).'%'):'');
|
||||
if ($disk['device'] && !strpos($state,'blink')) my_smart($row6[$n],$disk['name'],'Device');
|
||||
my_usage($row7[$n],($disk['type']!='Parity' && $disk['fsStatus']=='Mounted')?(round((1-$disk['fsFree']/$disk['fsSize'])*100).'%'):'');
|
||||
}
|
||||
};
|
||||
foreach ($disks as $disk)
|
||||
if ($disk['type']=='Parity' && $disk['status']!='DISK_NP')
|
||||
$funcRenderRow($i++,$disk);
|
||||
foreach ($disks as $disk)
|
||||
if ($disk['type']=='Data' && $disk['status']!='DISK_NP')
|
||||
$funcRenderRow($i++,$disk);
|
||||
foreach ($disks as $disk)
|
||||
if ($disk['type']=='Cache' && $disk['status']!='DISK_NP') {
|
||||
if ($disk['name']!='cache') $disk['fsStatus']=='-';
|
||||
$funcRenderRow($i++,$disk);
|
||||
}
|
||||
foreach ($devs as $dev) {
|
||||
$device = $dev['device'];
|
||||
$state = exec("hdparm -C /dev/$device|grep -Po active") ? 'blue-on' : 'blue-blink';
|
||||
if ($state=='blue-on') my_smart($row6[$i],$device,'New');
|
||||
my_insert($row3[$i++],"<img src=$path/$state.png>");
|
||||
}
|
||||
foreach ($devs as $dev) my_insert($row3[$i++],"<img src=$path/blue-on.png>");
|
||||
echo "<tr>".implode('',$row1)."</tr>";
|
||||
echo "<tr>".implode('',$row2)."</tr>";
|
||||
echo "<tr>".implode('',$row3)."</tr>";
|
||||
@@ -139,20 +170,30 @@ case 'port':
|
||||
break;
|
||||
case 'port': exec("ifconfig -s|awk '/^(bond|eth|lo)/{print $3\"#\"$7}'",$ports); break;
|
||||
case 'link': exec("ifconfig -s|awk '/^(bond|eth|lo)/{print \"Errors: \"$4\"<br>Drops: \"$5\"<br>Overruns: \"$6\"#Errors: \"$8\"<br>Drops: \"$9\"<br>Overruns: \"$10}'",$ports); break;
|
||||
default: $ports = array();}
|
||||
default: $ports = [];}
|
||||
echo implode('#',$ports);
|
||||
break;
|
||||
case 'parity':
|
||||
$var = parse_ini_file("state/var.ini");
|
||||
echo "<span class='orange p0'><strong>".($var['mdNumInvalid']==0 ? 'Parity-Check' : ($var['mdInvalidDisk']==0 ? 'Parity-Sync' : 'Data-Rebuild'))." in progress... Completed: ".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),0)." %.</strong></span>".
|
||||
"<br><em>Elapsed time: ".my_clock(floor(($var['currTime']-$var['sbUpdated'])/60)).". Estimated finish: ".my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0))."</em>";
|
||||
$mode = '';
|
||||
if (strstr($var['mdResyncAction'],"recon")) {
|
||||
$mode = 'Parity-Sync / Data-Rebuild';
|
||||
} elseif (strstr($var['mdResyncAction'],"clear")) {
|
||||
$mode = 'Clearing';
|
||||
} elseif ($var['mdResyncAction']=="check") {
|
||||
$mode = 'Read-Check';
|
||||
} 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><em>Elapsed time: ".my_clock(floor(($var['currTime']-$var['sbUpdated'])/60)).". Estimated finish: ".my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0))."</em>";
|
||||
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 = array();
|
||||
$counts = array_count_values($lsof); $count = [];
|
||||
foreach ($names as $name) $count[] = isset($counts[$name]) ? $counts[$name] : 0;
|
||||
echo implode('#',$count);
|
||||
break;
|
||||
|
||||
@@ -40,6 +40,7 @@ Shadowbox.init({skipSetup:true});
|
||||
|
||||
// server uptime
|
||||
var uptime = <?=strtok(exec("cat /proc/uptime"),' ')?>;
|
||||
var before = new Date();
|
||||
|
||||
// Page refresh timer
|
||||
var update = <?=abs($display['refresh'])/1000?>;
|
||||
@@ -64,11 +65,13 @@ function plus(value, label, last) {
|
||||
return value>0 ? (value+' '+label+(value!=1?'s':'')+(last?'':', ')) : '';
|
||||
}
|
||||
function updateTime() {
|
||||
var now = new Date();
|
||||
days = parseInt(uptime/86400);
|
||||
hour = parseInt(uptime/3600%24);
|
||||
mins = parseInt(uptime/60%60);
|
||||
$('#uptime').html(((days|hour|mins)?plus(days,'day',(hour|mins)==0)+plus(hour,'hour',mins==0)+plus(mins,'minute',true):'less than a minute'));
|
||||
uptime++;
|
||||
uptime += Math.round((now.getTime() - before.getTime())/1000);
|
||||
before = now;
|
||||
setTimeout(updateTime,1000);
|
||||
}
|
||||
function refresh(top) {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$log = $_GET['log'];
|
||||
if (basename($log,'.notify')=='*') array_map('unlink',glob($log,GLOB_NOSORT)); else unlink($log);
|
||||
require_once 'Wrappers.php';
|
||||
|
||||
$dynamix = parse_plugin_cfg('dynamix',true);
|
||||
if (strpos($_POST['log'],'*')===false) @unlink("{$dynamix['notify']['path']}/archive/{$_POST['log']}"); else array_map('unlink',glob("{$dynamix['notify']['path']}/archive/{$_POST['log']}",GLOB_NOSORT));
|
||||
?>
|
||||
|
||||
@@ -11,216 +11,167 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once('Helpers.php');
|
||||
require_once 'Helpers.php';
|
||||
|
||||
$path = $_POST['path'];
|
||||
$width = $_POST['width'];
|
||||
$var = parse_ini_file("state/var.ini");
|
||||
$devs = parse_ini_file("state/devs.ini",true);
|
||||
$disks = parse_ini_file("state/disks.ini",true);
|
||||
$screen = '/tmp/screen_buffer';
|
||||
$path = $_POST['path'];
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$devs = parse_ini_file('state/devs.ini',true);
|
||||
$disks = parse_ini_file('state/disks.ini',true);
|
||||
$sum = ['count'=>0, 'temp'=>0, 'fsSize'=>0, 'fsUsed'=>0, 'fsFree'=>0, 'numReads'=>0, 'numWrites'=>0, 'numErrors'=>0];
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
$temps=0; $counts=0; $tot_size=0; $tot_used=0; $tot_free=0; $reads=0; $writes=0; $errors=0;
|
||||
require_once 'CustomMerge.php';
|
||||
|
||||
extract(parse_plugin_cfg("dynamix",true));
|
||||
|
||||
function device_info($disk) {
|
||||
global $path, $width, $var, $display, $screen;
|
||||
$href = $disk['name'];
|
||||
if ($href != 'preclear') {
|
||||
$name = my_disk($href);
|
||||
$type = $disk['type'];
|
||||
} else {
|
||||
$name = $disk['device'];
|
||||
$type = 'Preclear';
|
||||
$href = "{$disk['device']}&file=$screen";
|
||||
function in_parity_log($log,$timestamp) {
|
||||
if (file_exists($log)) {
|
||||
$handle = fopen($log, 'r');
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
if (strpos($line,$timestamp)!==false) break;
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
if ($var['fsState']=='Started' && $type!='Flash' && $type!='Preclear' && strpos($disk['status'], 'DISK_NP')===false) {
|
||||
$action = strpos($disk['color'],'blink')===false ? "down" : "up";
|
||||
$ctrl = "<a href='update.htm?cmdSpin{$action}={$href}' title='Click to spin $action device' class='none' target='progressFrame' onclick=\"$.removeCookie('one',{path:'/'});\"><i class='fa fa-sort-$action spacing'></i></a>";
|
||||
}
|
||||
else
|
||||
$ctrl = "";
|
||||
$ball = "/webGui/images/{$disk['color']}.png";
|
||||
return !empty($line);
|
||||
}
|
||||
function device_info(&$disk) {
|
||||
global $path, $var;
|
||||
$name = $disk['name'];
|
||||
$type = $disk['type']=='Flash' || $disk['type']=='New' ? $disk['type'] : 'Device';
|
||||
$action = strpos($disk['color'],'blink')===false ? 'down' : 'up';
|
||||
if ($var['fsState']=='Started' && $type!='Flash') {
|
||||
$cmd = $type=='New' ? "cmd=/webGui/scripts/hd_parm&arg1=$action&arg2=$name" : "cmdSpin$action=$name";
|
||||
$ctrl = "<a href='update.htm?$cmd' title='Click to spin $action device' class='none' target='progressFrame' onclick=\"$.removeCookie('one',{path:'/'});\"><i class='fa fa-sort-$action spacing'></i></a>";
|
||||
} else
|
||||
$ctrl = '';
|
||||
switch ($disk['color']) {
|
||||
case 'green-on': $help = 'Normal operation, device is active'; break;
|
||||
case 'green-blink': $help = 'Device is in standby mode (spun-down)'; break;
|
||||
case 'blue-on': $help = ($disk['name']=='preclear' ? 'Unassigned device' : 'New device'); break;
|
||||
case 'blue-blink': $help = ($disk['name']=='preclear' ? 'Unassigned device, in standby mode' : 'New device, in stadby mode (spun-down)'); break;
|
||||
case 'yellow-on': $help = ($disk['type']=='Parity' ? 'Parity is invalid' : 'Device contents emulated'); break;
|
||||
case 'yellow-blink': $help = 'Device contents emulated, in standby mode (spun-down)'; break;
|
||||
case 'red-on':
|
||||
case 'red-blink': $help = ($disk['type']=='Parity' ? 'Parity device is disabled' : 'Device is disabled, contents emulated'); break;
|
||||
case 'red-off': $help = ($disk['type']=='Parity' ? 'Parity device missing' : 'Device is missing (disabled), contents emulated'); break;
|
||||
case 'blue-on': $help = 'New device'; break;
|
||||
case 'blue-blink': $help = 'New device, in standby mode (spun-down)'; break;
|
||||
case 'yellow-on': $help = $disk['type']=='Parity' ? 'Parity is invalid' : 'Device contents emulated'; break;
|
||||
case 'yellow-blink': $help = $disk['type']=='Parity' ? 'Parity is invalid, in standby mode (spun-down)' : 'Device contents emulated, in standby mode (spun-down)'; break;
|
||||
case 'red-on': case 'red-blink': $help = $disk['type']=='Parity' ? 'Parity device is disabled' : 'Device is disabled, contents emulated'; break;
|
||||
case 'red-off': $help = $disk['type']=='Parity' ? 'Parity device is missing' : 'Device is missing (disabled), contents emulated'; break;
|
||||
case 'grey-off': $help = 'Device not present'; break;
|
||||
}
|
||||
switch ($type) {
|
||||
case 'Flash':
|
||||
$device = "Flash";
|
||||
break;
|
||||
default:
|
||||
$device = "Device";
|
||||
break;
|
||||
}
|
||||
$status = "<a class='info nohand' onclick='return false'><img src='$ball' class='icon'><span>${help}</span></a>";
|
||||
$link = strpos($disk['status'], 'DISK_NP')===false ? "<a href='$path/$device?name=$href'>$name</a>" : $name;
|
||||
return $ctrl.$status.$link;
|
||||
$status = "$ctrl<a class='info nohand' onclick='return false'><img src='/webGui/images/{$disk['color']}.png' class='icon'><span>$help</span></a>";
|
||||
$link = strpos($disk['status'], 'DISK_NP')===false ? "<a href='$path/$type?name=$name' title='".my_disk($name)." Settings'>".my_disk($name)."</a>" : my_disk($name);
|
||||
return $status.$link;
|
||||
}
|
||||
function device_browse($disk) {
|
||||
function device_browse(&$disk) {
|
||||
global $path;
|
||||
if ($disk['fsStatus']=='Mounted') {
|
||||
$dir = $disk['name']=="flash" ? "/boot" : "/mnt/{$disk['name']}";
|
||||
$dir = $disk['name']=='flash' ? "/boot" : "/mnt/{$disk['name']}";
|
||||
return "<a href='$path/Browse?dir=$dir'><img src='/webGui/images/explore.png' title='Browse $dir'></a>";
|
||||
}
|
||||
}
|
||||
function device_desc($disk) {
|
||||
function device_desc(&$disk) {
|
||||
global $var;
|
||||
$size = my_scale($disk['size']*1024, $unit);
|
||||
return "{$disk['id']} - $size $unit ({$disk['device']})";
|
||||
$size = my_scale($disk['size']*1024,$unit);
|
||||
$log = $var['fsState']=='Started' ? "<a href=\"#\" title=\"Disk Log Information\" onclick=\"openBox('/webGui/scripts/disk_log&arg1={$disk['device']}','Disk Log Information',600,900,false);return false\"><i class=\"fa fa-hdd-o icon\"></i></a>" : "";
|
||||
return "$log{$disk['id']} - $size $unit ({$disk['device']})";
|
||||
}
|
||||
function assignment($disk) {
|
||||
global $var, $disks, $devs, $screen;
|
||||
$out = "<form method='POST' name=\"{$disk['name']}Form\" action='/update.htm' target='progressFrame'>";
|
||||
$out .= "<input type='hidden' name='changeDevice' value='Apply'>";
|
||||
$out .= "<select style=\"max-width:none\" name=\"slotId.{$disk['idx']}\" onChange=\"{$disk['name']}Form.submit()\">";
|
||||
$empty = ($disk['idSb']!="" ? "no device" : "unassigned");
|
||||
if ($disk['id']!="") {
|
||||
function assignment(&$disk) {
|
||||
global $var, $devs;
|
||||
$out = "<form method='POST' name=\"{$disk['name']}Form\" action='/update.htm' target='progressFrame'><input type='hidden' name='changeDevice' value='Apply'>";
|
||||
$out .= "<select style=\"min-width:400px;max-width:400px\" name=\"slotId.{$disk['idx']}\" onChange=\"{$disk['name']}Form.submit()\">";
|
||||
$empty = ($disk['idSb']!='' ? 'no device' : 'unassigned');
|
||||
if ($disk['id']!='') {
|
||||
$out .= "<option value=\"{$disk['id']}\" selected>".device_desc($disk)."</option>";
|
||||
$out .= "<option value=''>$empty</option>";
|
||||
} else {
|
||||
} else
|
||||
$out .= "<option value='' selected>$empty</option>";
|
||||
}
|
||||
foreach ($devs as $dev) {
|
||||
if (!file_exists("{$screen}_{$dev['device']}")) {
|
||||
$out .= "<option value=\"{$dev['id']}\">".device_desc($dev)."</option>";
|
||||
}
|
||||
}
|
||||
return $out."</select></form>";
|
||||
foreach ($devs as $dev) {$out .= "<option value=\"{$dev['id']}\">".device_desc($dev)."</option>";}
|
||||
return "$out</select></form>";
|
||||
}
|
||||
function render_used_and_free($disk) {
|
||||
function fs_info(&$disk) {
|
||||
global $display;
|
||||
if ($disk['type']=='Parity' || $disk['fsStatus']=='-') {
|
||||
echo "<td colspan='4'></td>";
|
||||
echo "<td colspan='5'></td>";
|
||||
return;
|
||||
} else if ($disk['fsStatus']=='Mounted') {
|
||||
echo "<td>{$disk['fsType']}</td>";
|
||||
echo "<td>".my_scale($disk['fsSize']*1024, $unit)." $unit</td>";
|
||||
switch ($display['text']) {
|
||||
case 0:
|
||||
$text1 = true; $text2 = true; break;
|
||||
case 1: case 2:
|
||||
$text1 = false; $text2 = false; break;
|
||||
case 10: case 20:
|
||||
$text1 = true; $text2 = false; break;
|
||||
case 11: case 21:
|
||||
$text1 = false; $text2 = true; break;
|
||||
}
|
||||
if ($text1) {
|
||||
echo "<td>".my_scale($disk['fsUsed']*1024, $unit)." $unit</td>";
|
||||
echo "<td>".my_scale($disk['fsSize']*1024,$unit)." $unit</td>";
|
||||
if ($display['text']%10==0) {
|
||||
echo "<td>".my_scale($disk['fsUsed']*1024,$unit)." $unit</td>";
|
||||
} else {
|
||||
$used = $disk['fsSize'] ? 100 - round(100*$disk['fsFree']/$disk['fsSize']) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:{$used}%' class='".usage_color($used,false)."'><span>".my_scale($disk['fsUsed']*1024, $unit)." $unit</span></span></div></td>";
|
||||
$used = $disk['fsSize'] ? 100-round(100*$disk['fsFree']/$disk['fsSize']) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:$used%' class='".usage_color($disk,$used,false)."'><span>".my_scale($disk['fsUsed']*1024,$unit)." $unit</span></span></div></td>";
|
||||
}
|
||||
if ($text2) {
|
||||
echo "<td>".my_scale($disk['fsFree']*1024, $unit)." $unit</td>";
|
||||
if ($display['text']<10 ? $display['text']%10==0 : $display['text']%10!=0) {
|
||||
echo "<td>".my_scale($disk['fsFree']*1024,$unit)." $unit</td>";
|
||||
} else {
|
||||
$free = $disk['fsSize'] ? round(100*$disk['fsFree']/$disk['fsSize']) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:{$free}%' class='".usage_color($free,true)."'><span>".my_scale($disk['fsFree']*1024, $unit)." $unit</span></span></div></td>";
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:$free%' class='".usage_color($disk,$free,true)."'><span>".my_scale($disk['fsFree']*1024,$unit)." $unit</span></span></div></td>";
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
echo "<td colspan='2'></td><td>{$disk['fsStatus']}</td><td></td>";
|
||||
}
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
}
|
||||
function array_offline($disk) {
|
||||
function array_offline(&$disk) {
|
||||
echo "<tr>";
|
||||
switch ($disk['status']) {
|
||||
case "DISK_NP":
|
||||
case "DISK_OK_NP":
|
||||
case "DISK_NP_DSBL":
|
||||
case 'DISK_NP':
|
||||
case 'DISK_OK_NP':
|
||||
case 'DISK_NP_DSBL':
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>".assignment($disk)."</td>";
|
||||
echo "<td colspan='9'></td>";
|
||||
break;
|
||||
case "DISK_OK":
|
||||
case "DISK_INVALID":
|
||||
case "DISK_DSBL":
|
||||
case "DISK_DSBL_NEW":
|
||||
case "DISK_NEW":
|
||||
case 'DISK_OK':
|
||||
case 'DISK_INVALID':
|
||||
case 'DISK_DSBL':
|
||||
case 'DISK_DSBL_NEW':
|
||||
case 'DISK_NEW':
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>".assignment($disk)."</td>";
|
||||
echo "<td>".my_temp($disk['temp'])."</td>";
|
||||
echo "<td colspan='8'></td>";
|
||||
break;
|
||||
case "DISK_NP_MISSING":
|
||||
case 'DISK_NP_MISSING':
|
||||
echo "<td>".device_info($disk)."<span class='diskinfo'><em>Missing</em></span></td>";
|
||||
echo "<td>".assignment($disk)."<em>{$disk['idSb']} - ".my_scale($disk['sizeSb']*1024, $unit)." $unit</em></td>";
|
||||
echo "<td>".assignment($disk)."<em>{$disk['idSb']} - ".my_scale($disk['sizeSb']*1024,$unit)." $unit</em></td>";
|
||||
echo "<td colspan='9'></td>";
|
||||
break;
|
||||
case "DISK_WRONG":
|
||||
case 'DISK_WRONG':
|
||||
echo "<td>".device_info($disk)."<span class='diskinfo'><em>Wrong</em></span></td>";
|
||||
echo "<td>".assignment($disk)."<em>{$disk['idSb']} - ".my_scale($disk['sizeSb']*1024, $unit)." $unit</em></td>";
|
||||
echo "<td>".assignment($disk)."<em>{$disk['idSb']} - ".my_scale($disk['sizeSb']*1024,$unit)." $unit</em></td>";
|
||||
echo "<td>".my_temp($disk['temp'])."</td>";
|
||||
echo "<td colspan='8'></td>";
|
||||
break;
|
||||
}
|
||||
echo "</tr>";
|
||||
}
|
||||
function array_online($disk) {
|
||||
global $display, $temps, $counts, $tot_size, $tot_used, $tot_free, $reads, $writes, $errors;
|
||||
function array_online(&$disk) {
|
||||
global $sum;
|
||||
if (is_numeric($disk['temp'])) {
|
||||
$temps += $disk['temp'];
|
||||
$counts++;
|
||||
$sum['count']++;
|
||||
$sum['temp'] += $disk['temp'];
|
||||
}
|
||||
$reads += $disk['numReads'];
|
||||
$writes += $disk['numWrites'];
|
||||
$errors += $disk['numErrors'];
|
||||
if (isset($disk['fsFree']) && $disk['type']!='Parity') {
|
||||
$disk['fsUsed'] = $disk['fsSize'] - $disk['fsFree'];
|
||||
$tot_size += $disk['fsSize'];
|
||||
$tot_free += $disk['fsFree'];
|
||||
$tot_used += $disk['fsUsed'];
|
||||
$sum['numReads'] += $disk['numReads'];
|
||||
$sum['numWrites'] += $disk['numWrites'];
|
||||
$sum['numErrors'] += $disk['numErrors'];
|
||||
if (isset($disk['fsFree'])) {
|
||||
$disk['fsUsed'] = $disk['fsSize']-$disk['fsFree'];
|
||||
$sum['fsSize'] += $disk['fsSize'];
|
||||
$sum['fsUsed'] += $disk['fsUsed'];
|
||||
$sum['fsFree'] += $disk['fsFree'];
|
||||
}
|
||||
echo "<tr>";
|
||||
switch ($disk['status']) {
|
||||
case "DISK_NP":
|
||||
// Suppress empty slots to keep device list short
|
||||
// this actually should be configurable
|
||||
case 'DISK_NP':
|
||||
// Suppress empty slots to keep device list short (make this configurable?)
|
||||
// echo "<td>".device_info($disk)."</td>";
|
||||
// echo "<td colspan='9'>Not installed</td>";
|
||||
// echo "<td></td>";
|
||||
break;
|
||||
case "DISK_OK_NP":
|
||||
case 'DISK_OK_NP':
|
||||
case 'DISK_NP_DSBL':
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>Not Installed</td>";
|
||||
echo "<td><em>Not installed</em></td>";
|
||||
echo "<td colspan='4'></td>";
|
||||
render_used_and_free($disk);
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
break;
|
||||
case "DISK_NP_DSBL":
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
if ($disk['type']=="Parity") {
|
||||
echo "<td>Not installed</td>";
|
||||
echo "<td colspan='9'></td>";
|
||||
} else {
|
||||
echo "<td><em>Not installed</em></td>";
|
||||
echo "<td colspan='4'></td>";
|
||||
render_used_and_free($disk);
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
}
|
||||
break;
|
||||
case "DISK_DSBL":
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>".device_desc($disk)."</td>";
|
||||
echo "<td>".my_temp($disk['temp'])."</td>";
|
||||
echo "<td>".my_number($disk['numReads'])."</td>";
|
||||
echo "<td>".my_number($disk['numWrites'])."</td>";
|
||||
echo "<td>".my_number($disk['numErrors'])."</td>";
|
||||
if ($disk['type']=="Parity") {
|
||||
echo "<td colspan='5'></td>";
|
||||
} else {
|
||||
render_used_and_free($disk);
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
}
|
||||
fs_info($disk);
|
||||
break;
|
||||
case 'DISK_DSBL':
|
||||
default:
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>".device_desc($disk)."</td>";
|
||||
@@ -228,8 +179,7 @@ function array_online($disk) {
|
||||
echo "<td>".my_number($disk['numReads'])."</td>";
|
||||
echo "<td>".my_number($disk['numWrites'])."</td>";
|
||||
echo "<td>".my_number($disk['numErrors'])."</td>";
|
||||
render_used_and_free($disk);
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
fs_info($disk);
|
||||
break;
|
||||
}
|
||||
echo "</tr>";
|
||||
@@ -241,53 +191,44 @@ function my_clock($time) {
|
||||
$mins = $time%60;
|
||||
return plus($days,'day',($hour|$mins)==0).plus($hour,'hour',$mins==0).plus($mins,'minute',true);
|
||||
}
|
||||
function read_disk($device, $item) {
|
||||
function read_disk(&$device, $item) {
|
||||
global $var;
|
||||
$smart = "/var/local/emhttp/smart/$device";
|
||||
if (!file_exists($smart) || (time()-filemtime($smart)>=$var['poll_attributes'])) exec("smartctl -n standby -A /dev/$device > $smart");
|
||||
$temp = exec("awk '/Temperature/{print \$10;exit}' $smart");
|
||||
switch ($item) {
|
||||
case 'color': return $temp ? 'blue-on' : 'blue-blink';
|
||||
case 'temp' : return $temp ? $temp : '*';
|
||||
case 'color':
|
||||
return exec("hdparm -C /dev/$device|grep -Po active") ? 'blue-on' : 'blue-blink';
|
||||
case 'temp':
|
||||
$smart = "/var/local/emhttp/smart/$device";
|
||||
if (!file_exists($smart) || (time()-filemtime($smart)>=$var['poll_attributes'])) exec("smartctl -n standby -A /dev/$device > $smart");
|
||||
$temp = exec("awk '\$1==190||\$1==194{print \$10;exit}' $smart");
|
||||
return $temp ? $temp : '*';
|
||||
}
|
||||
}
|
||||
function show_totals($text) {
|
||||
global $var, $display, $temps, $counts, $tot_size, $tot_used, $tot_free, $reads, $writes, $errors;
|
||||
global $var, $display, $sum;
|
||||
echo "<tr class='tr_last'>";
|
||||
echo "<td><img src='/webGui/images/sum.png' class='icon'>Total</td>";
|
||||
echo "<td>$text</td>";
|
||||
echo "<td>".($counts>0?my_temp(round($temps/$counts, 1)):'*')."</td>";
|
||||
echo "<td>".my_number($reads)."</td>";
|
||||
echo "<td>".my_number($writes)."</td>";
|
||||
echo "<td>".my_number($errors)."</td>";
|
||||
echo "<td>".($sum['count']>0 ? my_temp(round($sum['temp']/$sum['count'],1)) : '*')."</td>";
|
||||
echo "<td>".my_number($sum['numReads'])."</td>";
|
||||
echo "<td>".my_number($sum['numWrites'])."</td>";
|
||||
echo "<td>".my_number($sum['numErrors'])."</td>";
|
||||
echo "<td></td>";
|
||||
if (strstr($text,"Array") && ($var['startMode'] == "Normal")) {
|
||||
echo "<td>".my_scale($tot_size*1024, $unit)." $unit</td>";
|
||||
switch ($display['text']) {
|
||||
case 0:
|
||||
$text1 = true; $text2 = true; break;
|
||||
case 1: case 2:
|
||||
$text1 = false; $text2 = false; break;
|
||||
case 10: case 20:
|
||||
$text1 = true; $text2 = false; break;
|
||||
case 11: case 21:
|
||||
$text1 = false; $text2 = true; break;
|
||||
}
|
||||
if ($text1) {
|
||||
echo "<td>".my_scale($tot_used*1024, $unit)." $unit</td>";
|
||||
if (strstr($text,'Array') && ($var['startMode']=='Normal')) {
|
||||
echo "<td>".my_scale($sum['fsSize']*1024,$unit)." $unit</td>";
|
||||
if ($display['text']%10==0) {
|
||||
echo "<td>".my_scale($sum['fsUsed']*1024,$unit)." $unit</td>";
|
||||
} else {
|
||||
$used = $tot_size ? 100 - round(100*$tot_free/$tot_size) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:{$used}%' class='".usage_color($used,false)."'><span>".my_scale($tot_used*1024, $unit)." $unit</span></span></div></td>";
|
||||
$used = $sum['fsSize'] ? 100-round(100*$sum['fsFree']/$sum['fsSize']) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:$used%' class='".usage_color($display,$used,false)."'><span>".my_scale($sum['fsUsed']*1024,$unit)." $unit</span></span></div></td>";
|
||||
}
|
||||
if ($text2) {
|
||||
echo "<td>".my_scale($tot_free*1024, $unit)." $unit</td>";
|
||||
if ($display['text']<10 ? $display['text']%10==0 : $display['text']%10!=0) {
|
||||
echo "<td>".my_scale($sum['fsFree']*1024,$unit)." $unit</td>";
|
||||
} else {
|
||||
$free = $tot_size ? round(100*$tot_free/$tot_size) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:{$free}%' class='".usage_color($free,true)."'><span>".my_scale($tot_free*1024, $unit)." $unit</span></span></div></td>";
|
||||
$free = $sum['fsSize'] ? round(100*$sum['fsFree']/$sum['fsSize']) : 0;
|
||||
echo "<td><div class='usage-disk'><span style='margin:0;width:$free%' class='".usage_color($display,$free,true)."'><span>".my_scale($sum['fsFree']*1024,$unit)." $unit</span></span></div></td>";
|
||||
}
|
||||
echo "<td></td>";
|
||||
}
|
||||
else
|
||||
} else
|
||||
echo "<td colspan=4></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
@@ -295,13 +236,13 @@ function array_slots() {
|
||||
global $var;
|
||||
$min = max($var['sbNumDisks'], 3);
|
||||
$max = $var['MAX_ARRAYSZ'];
|
||||
$out = "";
|
||||
$out .= "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
$noparity2 = ($var['regTy']=='Pro')?0:1;
|
||||
$out = "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
$out .= "<input type='hidden' name='changeSlots' value='Apply'>";
|
||||
$out .= "<select name='SYS_ARRAY_SLOTS' onChange='this.form.submit()'>";
|
||||
$out .= "<select style='min-width:auto' name='SYS_ARRAY_SLOTS' onChange='this.form.submit()'>";
|
||||
for ($n=$min; $n<=$max; $n++) {
|
||||
$selected = ($n == $var['SYS_ARRAY_SLOTS'])? " selected" : "";
|
||||
$out .= "<option value='$n'{$selected}>$n</option>";
|
||||
$selected = ($n == $var['SYS_ARRAY_SLOTS'])? ' selected' : '';
|
||||
$out .= "<option value='$n'{$selected}>".($n-$noparity2)."</option>";
|
||||
}
|
||||
$out .= "</select></form>";
|
||||
return $out;
|
||||
@@ -310,13 +251,12 @@ function cache_slots() {
|
||||
global $var;
|
||||
$min = $var['cacheSbNumDisks'];
|
||||
$max = $var['MAX_CACHESZ'];
|
||||
$out = "";
|
||||
$out .= "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
$out = "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
$out .= "<input type='hidden' name='changeSlots' value='Apply'>";
|
||||
$out .= "<select name='SYS_CACHE_SLOTS' onChange='this.form.submit()'>";
|
||||
$out .= "<select style='min-width:auto' name='SYS_CACHE_SLOTS' onChange='this.form.submit()'>";
|
||||
for ($n=$min; $n<=$max; $n++) {
|
||||
$option = $n ? $n : "none";
|
||||
$selected = ($n == $var['SYS_CACHE_SLOTS'])? " selected" : "";
|
||||
$option = $n ? $n : 'none';
|
||||
$selected = ($n == $var['SYS_CACHE_SLOTS'])? ' selected' : '';
|
||||
$out .= "<option value='$n'{$selected}>$option</option>";
|
||||
}
|
||||
$out .= "</select></form>";
|
||||
@@ -331,12 +271,12 @@ case 'array':
|
||||
} else {
|
||||
foreach ($disks as $disk) {if ($disk['type']=='Parity') array_online($disk);}
|
||||
foreach ($disks as $disk) {if ($disk['type']=='Data') array_online($disk);}
|
||||
if ($display['total']) show_totals("Array of ".my_word($var['mdNumDisks'])." devices");
|
||||
if ($display['total']) show_totals('Array of '.my_word($var['mdNumDisks']).' devices');
|
||||
}
|
||||
break;
|
||||
case 'flash':
|
||||
$disk = &$disks['flash'];
|
||||
$disk['fsUsed'] = $disk['fsSize'] - $disk['fsFree'];
|
||||
$disk['fsUsed'] = $disk['fsSize']-$disk['fsFree'];
|
||||
echo "<tr>";
|
||||
echo "<td>".device_info($disk)."</td>";
|
||||
echo "<td>".device_desc($disk)."</td>";
|
||||
@@ -344,33 +284,30 @@ case 'flash':
|
||||
echo "<td>".my_number($disk['numReads'])."</td>";
|
||||
echo "<td>".my_number($disk['numWrites'])."</td>";
|
||||
echo "<td>".my_number($disk['numErrors'])."</td>";
|
||||
render_used_and_free($disk);
|
||||
echo "<td>".device_browse($disk)."</td>";
|
||||
fs_info($disk);
|
||||
echo "</tr>";
|
||||
break;
|
||||
case 'cache':
|
||||
if ($var['fsState']=='Stopped') {
|
||||
foreach ($disks as $disk) {if ($disk['type']=='Cache') array_offline($disk);}
|
||||
echo "<tr class='tr_last'><td><img src='/webGui/images/sum.png' class='icon'>Slots:</td><td colspan='9'>".cache_slots()."</td><td></td></tr>";
|
||||
echo "<tr><td colspan='10'></td><td></td></tr>";
|
||||
} else {
|
||||
foreach ($disks as $disk) {if ($disk['type']=='Cache') array_online($disk);}
|
||||
if ($display['total'] && $var['cacheSbNumDisks']>1) show_totals("Pool of ".my_word($var['cacheNumDevices'])." devices");
|
||||
if ($display['total'] && $var['cacheSbNumDisks']>1) show_totals('Pool of '.my_word($var['cacheNumDevices']).' devices');
|
||||
}
|
||||
break;
|
||||
case 'open':
|
||||
$status = isset($confirm['preclear']) ? '' : '_NP';
|
||||
foreach ($devs as $dev) {
|
||||
$dev['name'] = 'preclear';
|
||||
$dev['color'] = read_disk($dev['device'], 'color');
|
||||
$dev['temp'] = read_disk($dev['device'], 'temp');
|
||||
$dev['status'] = $status;
|
||||
$dev['name'] = $dev['device'];
|
||||
$dev['type'] = 'New';
|
||||
$dev['color'] = read_disk($dev['device'],'color');
|
||||
$dev['temp'] = read_disk($dev['device'],'temp');
|
||||
echo "<tr>";
|
||||
echo "<td>".device_info($dev)."</td>";
|
||||
echo "<td>".device_desc($dev)."</td>";
|
||||
echo "<td>".my_temp($dev['temp'])."</td>";
|
||||
if (file_exists("/tmp/preclear_stat_{$dev['device']}")) {
|
||||
$text = exec("cut -d'|' -f3 /tmp/preclear_stat_{$dev['device']} | sed 's:\^n:\<br\>:g'");
|
||||
$text = exec("cut -d'|' -f3 /tmp/preclear_stat_{$dev['device']}|sed 's:\^n:\<br\>:g'");
|
||||
if (strpos($text,'Total time')===false) $text = 'Preclear in progress... '.$text;
|
||||
echo "<td colspan='8' style='text-align:right'><em>$text</em></td>";
|
||||
} else
|
||||
@@ -381,13 +318,29 @@ case 'open':
|
||||
case 'parity':
|
||||
$data = array();
|
||||
if ($var['mdResync']>0) {
|
||||
$data[] = my_scale($var['mdResync']*1024, $unit)." $unit";
|
||||
$data[] = my_scale($var['mdResync']*1024,$unit)." $unit";
|
||||
$data[] = my_clock(floor(($var['currTime']-$var['sbUpdated'])/60));
|
||||
$data[] = my_scale($var['mdResyncPos']*1024, $unit)." $unit (".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),1,substr($display['number'],0,1),'')." %)";
|
||||
$data[] = my_scale($var['mdResyncDb']/$var['mdResyncDt']*1024, $unit, 1)." $unit/sec";
|
||||
$data[] = my_scale($var['mdResyncPos']*1024,$unit)." $unit (".number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),1,substr($display['number'],0,1),'')." %)";
|
||||
$data[] = my_scale($var['mdResyncDb']/$var['mdResyncDt']*1024,$unit, 1)." $unit/sec";
|
||||
$data[] = my_clock(round(((($var['mdResyncDt']*(($var['mdResync']-$var['mdResyncPos'])/($var['mdResyncDb']/100+1)))/100)/60),0));
|
||||
$data[] = $var['sbSyncErrs'];
|
||||
echo implode(';',$data);
|
||||
} else {
|
||||
if ($var['sbSynced']==0) break;
|
||||
$log = '/boot/config/parity-checks.log';
|
||||
$timestamp = str_replace(['.0','.'],[' ',' '],date('M.d H:i:s',$var['sbSynced']));
|
||||
if (in_parity_log($log,$timestamp)) break;
|
||||
exec("grep -Po '^$timestamp .*(sync done. \Ktime=\d+|sync completion \Kstatus: -?\d+)' /var/log/syslog", $rows);
|
||||
$duration = 0; $speed = 0; $status = 0;
|
||||
foreach ($rows as $row) {
|
||||
if (strpos($row,'time=')!==false) {
|
||||
$duration = substr($row,5);
|
||||
} elseif (strpos($row,'status:')!==false) {
|
||||
$status = substr($row,8);
|
||||
}
|
||||
}
|
||||
if ($duration>0) $speed = isset($disks['parity']['sizeSb']) ? my_scale($disks['parity']['sizeSb']*1024/$duration,$unit,1)." $unit/s" : "Unknown";
|
||||
file_put_contents($log,"$timestamp|$duration|$speed|$status\n",FILE_APPEND);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once 'Helpers.php';
|
||||
|
||||
$shares = parse_ini_file('state/shares.ini',true);
|
||||
$disks = parse_ini_file('state/disks.ini',true);
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$sec = parse_ini_file('state/sec.ini',true);
|
||||
$sec_nfs = parse_ini_file('state/sec_nfs.ini',true);
|
||||
$sec_afp = parse_ini_file('state/sec_afp.ini',true);
|
||||
$compute = $_GET['compute'];
|
||||
$path = $_GET['path'];
|
||||
$prev = $_GET['prev'];
|
||||
|
||||
$display = [];
|
||||
$display['scale'] = $_GET['scale'];
|
||||
$display['number'] = $_GET['number'];
|
||||
|
||||
// Display export settings
|
||||
function disk_share_settings($protocol,$share) {
|
||||
if (empty($share)) return;
|
||||
if ($protocol!='yes' || $share['export']=='-') return "-";
|
||||
if ($share['export']=='e') return ucfirst($share['security']);
|
||||
return '<em>'.ucfirst($share['security']).'</em>';
|
||||
}
|
||||
|
||||
function globalInclude($name) {
|
||||
global $var;
|
||||
return substr($name,0,4)!='disk' || !$var['shareUserInclude'] || strpos("{$var['shareUserInclude']},","$name,")!==false;
|
||||
}
|
||||
|
||||
function shareInclude($name) {
|
||||
global $include;
|
||||
return !$include || substr($name,0,4)!='disk' || strpos("$include,", "$name,")!==false;
|
||||
}
|
||||
|
||||
// Compute all disk shares
|
||||
if ($compute=='yes') foreach ($disks as $name => $disk) if ($disk['exportable']=='yes') exec("webGui/scripts/disk_size \"$name\" \"ssz2\"");
|
||||
|
||||
// global shares include/exclude
|
||||
$myDisks = array_filter(array_diff(array_keys($disks), explode(',',$var['shareUserExclude'])), 'globalInclude');
|
||||
|
||||
// Share size per disk
|
||||
$preserve = ($path==$prev || $compute=='yes');
|
||||
$ssz2 = array();
|
||||
foreach (glob("state/*.ssz2", GLOB_NOSORT) as $entry) {
|
||||
if ($preserve) {
|
||||
$ssz2[basename($entry, ".ssz2")] = parse_ini_file($entry);
|
||||
} else {
|
||||
unlink($entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Build table
|
||||
$row = 0;
|
||||
foreach ($disks as $name => $disk) {
|
||||
if ($disk['type']=='Flash') continue;
|
||||
if ($disk['fsColor']=='grey-off') continue;
|
||||
if ($disk['exportable']=='no') continue;
|
||||
$row++;
|
||||
$ball = "/webGui/images/{$disk['fsColor']}.png";
|
||||
switch ($disk['fsColor']) {
|
||||
case 'green-on': $help = 'All files protected'; break;
|
||||
case 'yellow-on': $help = 'All files unprotected'; break;
|
||||
}
|
||||
echo "<tr>";
|
||||
echo "<td><a class='info nohand' onclick='return false'><img src='$ball' class='icon'><span style='left:18px'>$help</span></a><a href='$path/Disk?name=$name' onclick=\"$.cookie('one','tab1',{path:'/'})\">$name</a></td>";
|
||||
echo "<td>{$disk['comment']}</td>";
|
||||
echo "<td>".disk_share_settings($var['shareSMBEnabled'], $sec[$name])."</td>";
|
||||
echo "<td>".disk_share_settings($var['shareNFSEnabled'], $sec_nfs[$name])."</td>";
|
||||
echo "<td>".disk_share_settings($var['shareAFPEnabled'], $sec_afp[$name])."</td>";
|
||||
$cmd="/webGui/scripts/disk_size"."&arg1=".urlencode($name)."&arg2=ssz2";
|
||||
if (array_key_exists($name, $ssz2)) {
|
||||
echo "<td>".my_scale(($disk['fsSize'])*1024, $unit)." $unit</td>";
|
||||
echo "<td>".my_scale($disk['fsFree']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='$path/Browse?dir=/mnt/$name'><img src='/webGui/images/explore.png' title='Browse /mnt/$name'></a></td>";
|
||||
echo "</tr>";
|
||||
foreach ($ssz2[$name] as $sharename => $sharesize) {
|
||||
if ($sharename=='share.total') continue;
|
||||
$include = $shares[$sharename]['include'];
|
||||
$inside = in_array($disk['name'], array_filter(array_diff($myDisks, explode(',',$shares[$sharename]['exclude'])), 'shareInclude'));
|
||||
echo "<tr class='share_status_size".($inside ? "'>" : " warning'>");
|
||||
echo "<td>$sharename:</td>";
|
||||
echo "<td>".($inside ? "" : "<em>Share is outside the list of designated disks</em>")."</td>";
|
||||
echo "<td></td>";
|
||||
echo "<td></td>";
|
||||
echo "<td></td>";
|
||||
echo "<td class='disk-$row-1'>".my_scale($sharesize*1024, $unit)." $unit</td>";
|
||||
echo "<td class='disk-$row-2'>".my_scale($disk['fsFree']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='/update.htm?cmd=$cmd' target='progressFrame' title='Recompute...' onclick='$(\".disk-$row-1\").html(\"Please wait...\");$(\".disk-$row-2\").html(\"\");'><i class='fa fa-refresh icon'></i></a></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
} else {
|
||||
echo "<td><a href='/update.htm?cmd=$cmd' target='progressFrame' onclick=\"$(this).text('Please wait...')\">Compute...</a></td>";
|
||||
echo "<td>".my_scale($disk['fsFree']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='$path/Browse?dir=/mnt/$name'><img src='/webGui/images/explore.png' title='Browse /mnt/$name'></a></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
}
|
||||
if ($row==0) {
|
||||
echo "<tr><td colspan='8' style='text-align:center'><i class='fa fa-folder-open-o icon'></i>There are no exportable disk shares</td></tr>";
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$keys = parse_ini_file($_POST['#cfg'], true);
|
||||
$text = "";
|
||||
|
||||
foreach ($_POST as $field => $value) {
|
||||
if ($field[0] == '#') continue;
|
||||
list($section,$key) = explode('_', $field, 2);
|
||||
$keys[$section][$key] = $value;
|
||||
}
|
||||
foreach ($keys as $section => $block) {
|
||||
$text .= "[$section]\n";
|
||||
foreach ($block as $key => $value) $text .= "$key=\"$value\"\n";
|
||||
}
|
||||
file_put_contents($_POST['#cfg'], $text);
|
||||
?>
|
||||
@@ -11,26 +11,28 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once('Wrappers.php');
|
||||
require_once 'Wrappers.php';
|
||||
|
||||
// Helper functions
|
||||
function my_scale($value, &$unit, $precision = NULL) {
|
||||
function my_scale($value, &$unit, $decimals = NULL) {
|
||||
global $display;
|
||||
$scale = $display['scale'];
|
||||
$number = $display['number'];
|
||||
$dot = substr($number,0,1);
|
||||
$comma = substr($number,1,1);
|
||||
$units = array('B','KB','MB','GB','TB','PB');
|
||||
if ($scale==0 && !$precision) {
|
||||
if ($scale==0 && $decimals==NULL) {
|
||||
$decimals = 0;
|
||||
$unit = '';
|
||||
return number_format($value, 0, $dot, ($value>=10000 ? $comma : ''));
|
||||
} else {
|
||||
$base = $value ? floor(log($value, 1000)) : 0;
|
||||
if ($scale>0 && $base>$scale) $base = $scale;
|
||||
$value /= pow(1000, $base);
|
||||
if ($decimals==NULL) $decimals = $value>=100 ? 0 : ($value>=10 ? 1 : (round($value*100)%100==0 ? 0 : 2));
|
||||
if ($scale<0 && round($value,$decimals)==1000) { $value = 1; $base++; }
|
||||
$unit = $units[$base];
|
||||
$value = round($value/pow(1000, $base), $precision ? $precision : 2);
|
||||
return number_format($value, $precision ? $precision : (($value-intval($value)==0 || $value>=100) ? 0 : ($value>=10 ? 1 : 2)), $dot, ($value>=10000 ? $comma : ''));
|
||||
}
|
||||
return number_format($value, $decimals, $number[0], $value>=10000 ? $number[1] : '');
|
||||
}
|
||||
function my_number($value) {
|
||||
global $display;
|
||||
@@ -58,7 +60,7 @@ function my_word($num) {
|
||||
return $num<count($words) ? $words[$num] : $num;
|
||||
}
|
||||
function my_usage() {
|
||||
global $disks,$var;
|
||||
global $disks,$var,$display;
|
||||
$arraysize=0;
|
||||
$arrayfree=0;
|
||||
foreach ($disks as $disk) {
|
||||
@@ -69,33 +71,34 @@ function my_usage() {
|
||||
}
|
||||
if ($var['fsNumMounted']>0) {
|
||||
$used = $arraysize ? 100-round(100*$arrayfree/$arraysize) : 0;
|
||||
echo "<div class='usage-bar'><span style='width:{$used}%' class='".usage_color($used,false)."'><span>{$used}%</span></span></div>";
|
||||
echo "<div class='usage-bar'><span style='width:{$used}%' class='".usage_color($display,$used,false)."'><span>{$used}%</span></span></div>";
|
||||
} else {
|
||||
echo "<div class='usage-bar'><span><center>".($var['fsState']=='Started'?'Maintenance':'off-line')."</center></span></div>";
|
||||
}
|
||||
}
|
||||
function usage_color($limit,$free) {
|
||||
function usage_color(&$disk,$limit,$free) {
|
||||
global $display;
|
||||
if ($display['text']==1 || intval($display['text']/10)==1) return '';
|
||||
$critical = !empty($disk['critical']) ? $disk['critical'] : $display['critical'];
|
||||
$warning = !empty($disk['warning']) ? $disk['warning'] : $display['warning'];
|
||||
if (!$free) {
|
||||
if ($limit>=$display['critical']) return 'redbar';
|
||||
if ($limit>=$display['warning']) return 'orangebar';
|
||||
if ($limit>=$critical) return 'redbar';
|
||||
if ($limit>=$warning) return 'orangebar';
|
||||
return 'greenbar';
|
||||
} else {
|
||||
if ($limit<=100-$display['critical']) return 'redbar';
|
||||
if ($limit<=100-$display['warning']) return 'orangebar';
|
||||
if ($limit<=100-$critical) return 'redbar';
|
||||
if ($limit<=100-$warning) return 'orangebar';
|
||||
return 'greenbar';
|
||||
}
|
||||
}
|
||||
function my_check($time) {
|
||||
global $var;
|
||||
if (!$time) return "unavailable (system reboot or log rotation)";
|
||||
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 = $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: ".my_scale($var['mdResyncSize']*1024/$time,$unit,1)." $unit/sec";
|
||||
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_error($code) {
|
||||
switch ($code) {
|
||||
@@ -140,6 +143,18 @@ function day_count($time) {
|
||||
function plus($val, $word, $last) {
|
||||
return $val>0 ? (($val || $last) ? ($val.' '.$word.($val!=1?'s':'').($last ?'':', ')) : '') : '';
|
||||
}
|
||||
function read_parity_log($epoch) {
|
||||
$log = '/boot/config/parity-checks.log';
|
||||
if (file_exists($log)) {
|
||||
$timestamp = str_replace(['.0','.'],[' ',' '],date('M.d H:i:s',$epoch));
|
||||
$handle = fopen($log, 'r');
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
if (strpos($line,$timestamp)!==false) break;
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
return $line ? $line : '0|0|0|0';
|
||||
}
|
||||
function urlencode_path($path) {
|
||||
return str_replace("%2F", "/", urlencode($path));
|
||||
}
|
||||
@@ -209,7 +224,7 @@ function transpose_user_path($path) {
|
||||
if (!empty($realdisk)) {
|
||||
// there may be several disks participating in this path (e.g. disk1,2,3) so
|
||||
// only return the first disk and replace 'user' with say 'cache' or 'disk1'
|
||||
$path = str_replace('/mnt/user/', '/mnt/'.strtok($realdisk.',', ',').'/', $dir);
|
||||
$path = str_replace('/mnt/user/', '/mnt/'.strtok($realdisk.',', ',').'/', $path);
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
|
||||
@@ -11,18 +11,33 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$files = glob($_POST['log'], GLOB_NOSORT);
|
||||
require_once 'Wrappers.php';
|
||||
|
||||
$dynamix = parse_plugin_cfg('dynamix',true);
|
||||
$files = glob("{$dynamix['notify']['path']}/archive/*.notify", GLOB_NOSORT);
|
||||
usort($files, create_function('$a,$b', 'return filemtime($b)-filemtime($a);'));
|
||||
|
||||
$row = 1;
|
||||
foreach ($files as $file) {
|
||||
$fields = preg_split('/\n/', file_get_contents($file));
|
||||
$fields = explode(PHP_EOL, file_get_contents($file));
|
||||
$archive = basename($file);
|
||||
if ($extra = count($fields)>6) {
|
||||
$td_ = "<td rowspan='3'><a href='#' onclick='openClose($row)'>"; $_td = "<i class='fa fa-anchor'></i></a></td>";
|
||||
} else {
|
||||
$td_ = "<td>"; $_td = "</td>";
|
||||
}
|
||||
$c = 0;
|
||||
foreach ($fields as $field) {
|
||||
if (!$field) continue;
|
||||
$item = explode('=', $field);
|
||||
if (!$c++) echo "<tr><td>".date("{$_POST['date']} {$_POST['time']}", $item[1])."</td>"; else echo "<td>{$item[1]}</td>";
|
||||
if ($c==5) break;
|
||||
$item = $field ? explode('=', $field, 2) : array("","-");
|
||||
echo (!$c++) ? "<tr>$td_".date("{$dynamix['notify']['date']} {$dynamix['notify']['time']}", $item[1])."$_td" : "<td>{$item[1]}</td>";
|
||||
}
|
||||
echo "<td style='text-align:right'><a href='#' onclick='$.post(\"/webGui/include/DeleteLogFile.php\",{log:\"$archive\"},function(){archiveList();});return false' title='Delete notification'><i class='fa fa-trash-o'></i></a></td></tr>";
|
||||
if ($extra) {
|
||||
$item = explode('=', $field, 2);
|
||||
echo "<tr class='expand-child row$row'><td colspan='5'>{$item[1]}</td></tr><tr class='expand-child row$row'><td colspan='5'></td></tr>";
|
||||
$row++;
|
||||
}
|
||||
echo "<td style='text-align:right'><a href='#' onclick='$.get(\"/webGui/include/DeleteLogFile.php\",{log:\"$file\"},function(){archiveList();});return false' title='Delete notification'><i class='fa fa-trash-o'></i></a></td></tr>";
|
||||
}
|
||||
if (empty($files)) echo "<tr><td colspan='6' style='text-align:center'><em>No notifications available</em></td></tr>";
|
||||
?>
|
||||
|
||||
@@ -11,7 +11,21 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once('Markdown.php');
|
||||
require_once 'Markdown.php';
|
||||
|
||||
function get_ini_key($key,$default) {
|
||||
$x = strpos($key, '[');
|
||||
$var = $x>0 ? substr($key,1,$x-1) : substr($key,1);
|
||||
global $$var;
|
||||
eval("\$var=$key;");
|
||||
return $var ? $var : $default;
|
||||
}
|
||||
|
||||
function get_file_key($file,$default) {
|
||||
list($key, $default) = explode('=',$default,2);
|
||||
$var = @parse_ini_file($file);
|
||||
return isset($var[$key]) ? $var[$key] : $default;
|
||||
}
|
||||
|
||||
function build_pages($pattern) {
|
||||
global $site;
|
||||
@@ -32,6 +46,10 @@ function find_pages($item) {
|
||||
foreach ($site as $page) {
|
||||
if (empty($page['Menu'])) continue;
|
||||
$menu = strtok($page['Menu'], ' ');
|
||||
switch ($menu[0]) {
|
||||
case '$': $menu = get_ini_key($menu,strtok(' ')); break;
|
||||
case '/': $menu = get_file_key($menu,strtok(' ')); break;
|
||||
}
|
||||
while ($menu !== false) {
|
||||
$add = explode(':', $menu);
|
||||
$add[] = '';
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
function plus($val, $word, $last) {
|
||||
return $val>0 ? (($val||$last)?($val.' '.$word.($last?'':', ')):'') : '';
|
||||
}
|
||||
function my_duration($time) {
|
||||
if (!$time) return 'Unavailable';
|
||||
$days = floor($time/86400);
|
||||
$hmss = $time-$days*86400;
|
||||
$hour = floor($hmss/3600);
|
||||
$mins = $hmss/60%60;
|
||||
$secs = $hmss%60;
|
||||
return plus($days,'day',($hour|$mins|$secs)==0).plus($hour,'hr',($mins|$secs)==0).plus($mins,'min',$secs==0).plus($secs,'sec',true);
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<link type="text/css" rel="stylesheet" href="/webGui/styles/default-fonts.css">
|
||||
<link type="text/css" rel="stylesheet" href="/webGui/styles/default-white.css">
|
||||
</head>
|
||||
<body>
|
||||
<table class='share_status' style='margin-top:0'><thead><tr><td>Date</td><td>Duration</td><td>Speed</td><td>Status</td></tr></thead><tbody>
|
||||
<?
|
||||
$log = '/boot/config/parity-checks.log'; $row = 0;
|
||||
if (file_exists($log)) {
|
||||
$handle = fopen($log, 'r');
|
||||
while (($line = fgets($handle)) !== false) {
|
||||
list($date,$duration,$speed,$status) = explode('|',$line);
|
||||
if ($speed==0) $speed = 'Unavailable';
|
||||
if ($duration>0||$status<>0) {echo "<tr><td>$date</td><td>".my_duration($duration)."</td><td>$speed</td><td>".($status==0?'OK':$status)."</td></tr>"; $row++;}
|
||||
}
|
||||
fclose($handle);
|
||||
}
|
||||
if ($row==0) echo "<tr><td colspan='4' style='text-align:center'>No parity check history present!</td></tr>";
|
||||
?>
|
||||
</tbody></table>
|
||||
<center><input type="button" value="Done" onclick="top.Shadowbox.close()"></center>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
// Preselected SMART codes for notifications
|
||||
$numbers = [];
|
||||
$preselect = [['code' => 5, 'set' => true, 'text' => 'Reallocated sectors count'],
|
||||
['code' => 187, 'set' => true, 'text' => 'Reported uncorrectable errors'],
|
||||
['code' => 188, 'set' => false,'text' => 'Command time-out'],
|
||||
['code' => 197, 'set' => true, 'text' => 'Current pending sector count'],
|
||||
['code' => 198, 'set' => true, 'text' => 'Uncorrectable sector count']];
|
||||
|
||||
for ($x = 0; $x < count($preselect); $x++) if ($preselect[$x]['set']) $numbers[] = $preselect[$x]['code'];
|
||||
?>
|
||||
@@ -0,0 +1,114 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once 'Helpers.php';
|
||||
|
||||
$shares = parse_ini_file('state/shares.ini',true);
|
||||
$disks = parse_ini_file('state/disks.ini',true);
|
||||
$var = parse_ini_file('state/var.ini');
|
||||
$sec = parse_ini_file('state/sec.ini',true);
|
||||
$sec_nfs = parse_ini_file('state/sec_nfs.ini',true);
|
||||
$sec_afp = parse_ini_file('state/sec_afp.ini',true);
|
||||
$compute = $_GET['compute'];
|
||||
$path = $_GET['path'];
|
||||
$prev = $_GET['prev'];
|
||||
|
||||
$display = [];
|
||||
$display['scale'] = $_GET['scale'];
|
||||
$display['number'] = $_GET['number'];
|
||||
|
||||
if (!$shares) {
|
||||
echo "<tr><td colspan='8' style='text-align:center'>There are no user shares</td></tr>";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Display export settings
|
||||
function user_share_settings($protocol,$share) {
|
||||
if (empty($share)) return;
|
||||
if ($protocol!='yes' || $share['export']=='-') return "-";
|
||||
if ($share['export']=='e') return ucfirst($share['security']);
|
||||
return '<em>'.ucfirst($share['security']).'</em>';
|
||||
}
|
||||
|
||||
function globalInclude($name) {
|
||||
global $var;
|
||||
return substr($name,0,4)!='disk' || !$var['shareUserInclude'] || strpos("{$var['shareUserInclude']},","$name,")!==false;
|
||||
}
|
||||
|
||||
function shareInclude($name) {
|
||||
global $include;
|
||||
return !$include || substr($name,0,4)!='disk' || strpos("$include,", "$name,")!==false;
|
||||
}
|
||||
|
||||
// Compute all user shares
|
||||
if ($compute=='yes') foreach ($shares as $name => $share) exec("webGui/scripts/share_size \"$name\" \"ssz1\"");
|
||||
|
||||
// global shares include/exclude
|
||||
$myDisks = array_filter(array_diff(array_keys($disks), explode(',',$var['shareUserExclude'])), 'globalInclude');
|
||||
|
||||
// Share size per disk
|
||||
$preserve = ($path==$prev || $compute=='yes');
|
||||
$ssz1 = array();
|
||||
foreach (glob("state/*.ssz1", GLOB_NOSORT) as $entry) {
|
||||
if ($preserve)
|
||||
$ssz1[basename($entry, ".ssz1")] = parse_ini_file($entry);
|
||||
else
|
||||
unlink($entry);
|
||||
}
|
||||
|
||||
// Build table
|
||||
$row = 0;
|
||||
foreach ($shares as $name => $share) {
|
||||
$row++;
|
||||
$ball = "/webGui/images/{$share['color']}.png";
|
||||
switch ($share['color']) {
|
||||
case 'green-on': $help = 'All files protected'; break;
|
||||
case 'yellow-on': $help = 'Some or all files unprotected'; break;
|
||||
}
|
||||
echo "<tr>";
|
||||
echo "<td><a class='info nohand' onclick='return false'><img src='$ball' class='icon'><span style='left:18px'>$help</span></a><a href='$path/Share?name=".urlencode($name)."' onclick=\"$.cookie('one','tab1',{path:'/'})\">$name</a></td>";
|
||||
echo "<td>{$share['comment']}</td>";
|
||||
echo "<td>".user_share_settings($var['shareSMBEnabled'], $sec[$name])."</td>";
|
||||
echo "<td>".user_share_settings($var['shareNFSEnabled'], $sec_nfs[$name])."</td>";
|
||||
echo "<td>".user_share_settings($var['shareAFPEnabled'], $sec_afp[$name])."</td>";
|
||||
$cmd="/webGui/scripts/share_size"."&arg1=".urlencode($name)."&arg2=ssz1";
|
||||
if (array_key_exists($name, $ssz1)) {
|
||||
echo "<td>".my_scale($ssz1[$name]['disk.total']*1024, $unit)." $unit</td>";
|
||||
echo "<td>".my_scale($share['free']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='$path/Browse?dir=/mnt/user/".urlencode($name)."'><img src='/webGui/images/explore.png' title='Browse /mnt/user/".urlencode($name)."'></a></td>";
|
||||
echo "</tr>";
|
||||
foreach ($ssz1[$name] as $diskname => $disksize) {
|
||||
if ($diskname=='disk.total') continue;
|
||||
$include = $share['include'];
|
||||
$inside = in_array($diskname, array_filter(array_diff($myDisks, explode(',',$share['exclude'])), 'shareInclude'));
|
||||
echo "<tr class='share_status_size".($inside ? "'>" : " warning'>");
|
||||
echo "<td>".my_disk($diskname).":</td>";
|
||||
echo "<td>".($inside ? "" : "<em>Share is outside the list of designated disks</em>")."</td>";
|
||||
echo "<td></td>";
|
||||
echo "<td></td>";
|
||||
echo "<td></td>";
|
||||
echo "<td class='share-$row-1'>".my_scale($disksize*1024, $unit)." $unit</td>";
|
||||
echo "<td class='share-$row-2'>".my_scale($disks[$diskname]['fsFree']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='/update.htm?cmd=$cmd' target='progressFrame' title='Recompute...' onclick='$(\".share-$row-1\").html(\"Please wait...\");$(\".share-$row-2\").html(\"\");'><i class='fa fa-refresh icon'></i></a></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
} else {
|
||||
echo "<td><a href='/update.htm?cmd=$cmd' target='progressFrame' onclick=\"$(this).text('Please wait...')\">Compute...</a></td>";
|
||||
echo "<td>".my_scale($share['free']*1024, $unit)." $unit</td>";
|
||||
echo "<td><a href='$path/Browse?dir=/mnt/user/".urlencode($name)."'><img src='/webGui/images/explore.png' title='Browse /mnt/user/".urlencode($name)."'></a></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
}
|
||||
if ($row==0) {
|
||||
echo "<tr><td colspan='8' style='text-align:center'><i class='fa fa-folder-open-o icon'></i>There are no exportable user shares</td></tr>";
|
||||
}
|
||||
@@ -11,90 +11,137 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once('Wrappers.php');
|
||||
|
||||
function duration($h) {
|
||||
function normalize($text, $glue='_') {
|
||||
$words = explode($glue,$text);
|
||||
foreach ($words as &$word) $word = $word==strtoupper($word) ? $word : preg_replace(['/^(ct|cnt)$/','/^blk$/'],['count','block'],strtolower($word));
|
||||
return "<td>".ucfirst(implode(' ',$words))."</td>";
|
||||
}
|
||||
function duration(&$hrs) {
|
||||
$time = ceil(time()/3600)*3600;
|
||||
$now = new DateTime("@$time");
|
||||
$poh = new DateTime("@".($time-$h*3600));
|
||||
$poh = new DateTime("@".($time-$hrs*3600));
|
||||
$age = date_diff($poh,$now);
|
||||
return " (".($age->y?"{$age->y}y, ":"").($age->m?"{$age->m}m, ":"").($age->d?"{$age->d}d, ":"")."{$age->h}h)";
|
||||
$hrs = "$hrs (".($age->y?"{$age->y}y, ":"").($age->m?"{$age->m}m, ":"").($age->d?"{$age->d}d, ":"")."{$age->h}h)";
|
||||
}
|
||||
function spindownDelay($port) {
|
||||
$disks = parse_ini_file('state/disks.ini',true);
|
||||
foreach ($disks as $disk) {
|
||||
if ($disk['device']==$port) { file_put_contents("/var/tmp/diskSpindownDelay.{$disk['idx']}", $disk['spindownDelay']); break; }
|
||||
}
|
||||
}
|
||||
$disks = []; $var = [];
|
||||
require_once 'CustomMerge.php';
|
||||
$name = isset($_POST['name']) ? $_POST['name'] : '';
|
||||
$port = isset($_POST['port']) ? $_POST['port'] : '';
|
||||
if ($name) {
|
||||
$disk = &$disks[$name];
|
||||
$type = isset($disk['smType']) ? $disk['smType'] : -1; if ($type==-1) $type = isset($var['smType']) ? $var['smType'] : '';
|
||||
if ($type) {
|
||||
$ports = [];
|
||||
if (isset($disk['smDevice']) && strlen($disk['smDevice'])) $port = $disk['smDevice'];
|
||||
if (isset($disk['smPort1']) && strlen($disk['smPort1'])) $ports[] = $disk['smPort1'];
|
||||
if (isset($disk['smPort2']) && strlen($disk['smPort2'])) $ports[] = $disk['smPort2'];
|
||||
if (isset($disk['smPort3']) && strlen($disk['smPort3'])) $ports[] = $disk['smPort3'];
|
||||
if ($ports) {
|
||||
$glue = isset($disk['smGlue']) ? $disk['smGlue'] : ',';
|
||||
$type .= ','.implode($glue,$ports);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$port = $_POST['port'];
|
||||
|
||||
switch ($_POST['cmd']) {
|
||||
case "attributes":
|
||||
$unraid = parse_plugin_cfg("dynamix",true);
|
||||
$events = explode('|', $unraid['notify']['events']);
|
||||
$temps = array(190,194);
|
||||
require_once 'Wrappers.php';
|
||||
require_once 'Preselect.php';
|
||||
$select = isset($disk['smSelect']) ? $disk['smSelect'] : -1; if ($select==-1) $select = isset($var['smSelect']) ? $var['smSelect'] : 0;
|
||||
$level = isset($disk['smLevel']) ? $disk['smLevel'] : -1; if ($level==-1) $level = isset($var['smLevel']) ? $var['smLevel'] : 1;
|
||||
$events = isset($disk['smEvents']) ? explode('|',$disk['smEvents']) : (isset($var['smEvents']) ? explode('|',$var['smEvents']) : $numbers);
|
||||
$temps = [190,194];
|
||||
$unraid = parse_plugin_cfg('dynamix',true);
|
||||
$max = $unraid['display']['max'];
|
||||
$hot = $unraid['display']['hot'];
|
||||
exec("smartctl -A /dev/$port|awk 'NR>7'",$output);
|
||||
exec("smartctl -A $type /dev/$port|awk 'NR>7'",$output);
|
||||
$empty = true;
|
||||
foreach ($output as $line) {
|
||||
if (!$line) continue;
|
||||
$info = explode(' ', trim(preg_replace('/\s+/',' ',$line)), 10);
|
||||
$color = "";
|
||||
if (array_search($info[0], $events)!==false && $info[9]>0) $color = " class='orange-text'";
|
||||
else if (array_search($info[0], $temps)!==false) {
|
||||
if ($info[9]>=$max) $color = " class='red-text'"; else if ($info[9]>=$hot) $color = " class='orange-text'";
|
||||
$highlight = strpos($info[8],'FAILING_NOW')!==false || ($select ? $info[5]>0 && $info[3]<=$info[5]*$level : $info[9]>0);
|
||||
if (in_array($info[0], $events) && $highlight) $color = " class='warn'";
|
||||
else if (in_array($info[0], $temps)) {
|
||||
if ($info[9]>=$max) $color = " class='alert'"; else if ($info[9]>=$hot) $color = " class='warn'";
|
||||
}
|
||||
echo "<tr{$color}>";
|
||||
if ($info[0] == 9 && is_numeric($info[9])) $info[9] .= duration($info[9]);
|
||||
foreach ($info as $field) echo "<td>".str_replace('_',' ',$field)."</td>";
|
||||
echo "</tr>";
|
||||
if ($info[8]=='-') $info[8] = 'Never';
|
||||
if ($info[0]==9 && is_numeric($info[9])) duration($info[9]);
|
||||
echo "<tr{$color}>".implode('',array_map('normalize', $info))."</tr>";
|
||||
$empty = false;
|
||||
}
|
||||
if ($empty) echo "<tr><td colspan='10' style='text-align:center'>Can not read attributes</td></tr>";
|
||||
break;
|
||||
case "capabilities":
|
||||
exec("smartctl -c /dev/$port|awk 'NR>5'",$output);
|
||||
$row = ["","",""];
|
||||
exec("smartctl -c $type /dev/$port|awk 'NR>5'",$output);
|
||||
$row = ['','',''];
|
||||
$empty = true;
|
||||
foreach ($output as $line) {
|
||||
if (!$line) continue;
|
||||
$line = preg_replace('/^_/','__',preg_replace(array('/__+/','/_ +_/'),'_',str_replace(array(chr(9),')','('),'_',$line)));
|
||||
$line = preg_replace('/^_/','__',preg_replace(['/__+/','/_ +_/'],'_',str_replace([chr(9),')','('],'_',$line)));
|
||||
$info = array_map('trim', explode('_', preg_replace('/_( +)_ /','__',$line), 3));
|
||||
if (isset($info[0])) $row[0] .= ($row[0] ? " " : "").$info[0];
|
||||
if (isset($info[1])) $row[1] .= ($row[1] ? " " : "").$info[1];
|
||||
if (isset($info[2])) $row[2] .= ($row[2] ? " " : "").$info[2];
|
||||
if (substr($row[2],-1)=='.') {
|
||||
echo "<tr><td>{$row[0]}</td><td>{$row[1]}</td><td>{$row[2]}</td></tr>";
|
||||
$row = ["","",""];
|
||||
echo "<tr><td>${row[0]}</td><td>${row[1]}</td><td>${row[2]}</td></tr>";
|
||||
$row = ['','',''];
|
||||
$empty = false;
|
||||
}
|
||||
}
|
||||
if ($empty) echo "<tr><td colspan='3' style='text-align:center'>Can not read capabilities</td></tr>";
|
||||
break;
|
||||
case "identify":
|
||||
exec("smartctl -i /dev/$port|awk 'NR>4'",$output);
|
||||
exec("smartctl -H /dev/$port|grep 'result'|sed 's:self-assessment test result::'",$output);
|
||||
$passed = ['PASSED','OK'];
|
||||
$failed = ['FAILED','NOK'];
|
||||
exec("smartctl -i $type /dev/$port|awk 'NR>4'",$output);
|
||||
exec("smartctl -H $type /dev/$port|grep -Pom1 '^SMART.*: [A-Z]+'|sed 's:self-assessment test result::'",$output);
|
||||
$empty = true;
|
||||
foreach ($output as $line) {
|
||||
if (!strlen($line)) continue;
|
||||
$info = array_map('trim', explode(':', $line, 2));
|
||||
if ($info[1]=='PASSED') $info[1] = "<span class='green-text'>Passed</span>";
|
||||
if ($info[1]=='FAILED') $info[1] = "<span class='red-text'>Failed</span>";
|
||||
echo "<tr><td>".preg_replace("/ is$/","",$info[0]).":</td><td>$info[1]</td></tr>";
|
||||
if (strpos($line,'VALID ARGUMENTS')!==false) break;
|
||||
list($title,$info) = array_map('trim', explode(':', $line, 2));
|
||||
if (in_array($info,$passed)) $info = "<span class='green-text'>Passed</span>";
|
||||
if (in_array($info,$failed)) $info = "<span class='red-text'>Failed</span>";
|
||||
echo "<tr>".normalize(preg_replace('/ is:$/',':',"$title:"),' ')."<td>$info</td></tr>";
|
||||
$empty = false;
|
||||
}
|
||||
if ($empty) echo "<tr><td colspan='2' style='text-align:center'>Can not read identification</td></tr>";
|
||||
break;
|
||||
case "save":
|
||||
exec("smartctl -a /dev/$port >{$_SERVER['DOCUMENT_ROOT']}/{$_POST['file']}");
|
||||
exec("smartctl -a $type /dev/$port >{$_SERVER['DOCUMENT_ROOT']}/{$_POST['file']}");
|
||||
break;
|
||||
case "delete":
|
||||
@unlink("/var/tmp/{$_POST['file']}");
|
||||
break;
|
||||
case "short":
|
||||
exec("smartctl -t short /dev/$port");
|
||||
spindownDelay($port);
|
||||
exec("smartctl -t short $type /dev/$port");
|
||||
break;
|
||||
case "long":
|
||||
exec("smartctl -t long /dev/$port");
|
||||
spindownDelay($port);
|
||||
exec("smartctl -t long $type /dev/$port");
|
||||
break;
|
||||
case "stop":
|
||||
exec("smartctl -X /dev/$port");
|
||||
exec("smartctl -X $type /dev/$port");
|
||||
break;
|
||||
case "update":
|
||||
if (!exec("hdparm -C /dev/$port|grep -om1 active")) {
|
||||
echo "<a href='/update.htm?cmdSpinup={$_POST['name']}' class='info' target='progressFrame'><input type='button' value='Spin Up'></a><span class='orange-text'><big>Unavailable - disk must be spun up</big></span>";
|
||||
if (!exec("hdparm -C /dev/$port|grep -Pom1 'active|unknown'")) {
|
||||
$cmd = $_POST['type']=='New' ? "cmd=/webGui/scripts/hd_parm&arg1=up&arg2=$name" : "cmdSpinup=$name";
|
||||
echo "<a href='/update.htm?$cmd' class='info' target='progressFrame'><input type='button' value='Spin Up'></a><span class='orange-text'><big>Unavailable - disk must be spun up</big></span>";
|
||||
break;
|
||||
}
|
||||
$progress = exec("smartctl -c /dev/$port|grep -Pom1 '\d+%'");
|
||||
$progress = exec("smartctl -c $type /dev/$port|grep -Pom1 '\d+%'");
|
||||
if ($progress) {
|
||||
echo "<big><i class='fa fa-spinner fa-pulse'></i> ".(100-substr($progress,0,-1))."% complete</big>";
|
||||
echo "<big><i class='fa fa-spinner fa-pulse'></i> self-test in progress, ".(100-substr($progress,0,-1))."% complete</big>";
|
||||
break;
|
||||
}
|
||||
$result = trim(exec("smartctl -l selftest /dev/$port|grep -m1 '^# 1'|cut -c26-55"));
|
||||
$result = trim(exec("smartctl -l selftest $type /dev/$port|grep -m1 '^# 1'|cut -c26-55"));
|
||||
if (!$result) {
|
||||
echo "<big>No self-tests logged on this disk</big>";
|
||||
break;
|
||||
@@ -110,10 +157,10 @@ case "update":
|
||||
echo "<span class='red-text'><big>Errors occurred - Check SMART report</big></span>";
|
||||
break;
|
||||
case "selftest":
|
||||
echo shell_exec("smartctl -l selftest /dev/$port|awk 'NR>5'");
|
||||
echo shell_exec("smartctl -l selftest $type /dev/$port|awk 'NR>5'");
|
||||
break;
|
||||
case "errorlog":
|
||||
echo shell_exec("smartctl -l error /dev/$port|awk 'NR>5'");
|
||||
echo shell_exec("smartctl -l error $type /dev/$port|awk 'NR>5'");
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -22,7 +22,17 @@ default:
|
||||
echo '<span class="green"><strong>Array Started</strong></span>'; break;
|
||||
}
|
||||
if ($var['mdResync']) {
|
||||
echo '•<span class="orange"><strong>'.($var['mdNumInvalid']==0 ? 'Parity-Check:' : ($var['mdInvalidDisk']==0 ? 'Parity-Sync:' : 'Data-Rebuild:')).' '.number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),1,$_POST['dot'],'').' %</strong></span>';
|
||||
$mode = '';
|
||||
if (strstr($var['mdResyncAction'],"recon")) {
|
||||
$mode = 'Parity-Sync / Data-Rebuild';
|
||||
} elseif (strstr($var['mdResyncAction'],"clear")) {
|
||||
$mode = 'Clearing';
|
||||
} elseif ($var['mdResyncAction']=="check") {
|
||||
$mode = 'Read-Check';
|
||||
} elseif (strstr($var['mdResyncAction'],"check")) {
|
||||
$mode = 'Parity-Check';
|
||||
}
|
||||
echo '•<span class="orange"><strong>'.$mode.' '.number_format(($var['mdResyncPos']/($var['mdResync']/100+1)),1,$_POST['dot'],'').' %</strong></span>';
|
||||
if ($_POST['mode']<0) echo '#stop';
|
||||
}
|
||||
?>
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
require_once "webGui/include/Wrappers.php";
|
||||
require_once 'webGui/include/Wrappers.php';
|
||||
|
||||
$memory = '/tmp/memory.tmp';
|
||||
if (isset($_POST['#apply'])) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?PHP
|
||||
/* Copyright 2015, Lime Technology
|
||||
* Copyright 2015, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
if (isset($_POST['#default'])) {
|
||||
$text = '';
|
||||
if (isset($_POST['#section'])) {
|
||||
unset($keys[$_POST['#section']]);
|
||||
foreach ($keys as $section => $block) {
|
||||
$text .= "[$section]\n";
|
||||
foreach ($block as $key => $value) $text .= "$key=\"$value\"\n";
|
||||
}
|
||||
}
|
||||
if ($text) file_put_contents($file, $text); else @unlink($file);
|
||||
$save = false;
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user