mirror of
https://github.com/unraid/webgui.git
synced 2026-04-20 17:02:10 -05:00
Multi cache pools
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
Menu="Main:2"
|
||||
Title="Cache Devices"
|
||||
Title="Pool Devices"
|
||||
Tag="bullseye"
|
||||
Cond="($var['fsState']=='Stopped' || $var['cacheSbNumDisks'])"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2020, Lime Technology
|
||||
@@ -15,12 +14,66 @@ Cond="($var['fsState']=='Stopped' || $var['cacheSbNumDisks'])"
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
function cache_only($disk) {
|
||||
return $disk['type']=='Cache';
|
||||
}
|
||||
function prefix($key) {
|
||||
return preg_replace('/[0-9]+$/','',$key);
|
||||
}
|
||||
$cache = array_filter($disks,'cache_only');
|
||||
$pools = array_unique(array_map('prefix',array_keys($cache)));
|
||||
$i = 0;
|
||||
?>
|
||||
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/jquery.ui.css")?>">
|
||||
|
||||
<script>
|
||||
function cache_status() {
|
||||
$.post('/webGui/include/DeviceList.php',{path:'<?=$path?>',device:'cache'},function(data) {
|
||||
if (data) {$('#cache_device').html(data); display_diskio();}
|
||||
function addPoolPopup() {
|
||||
var popup = $('#dialogAddPool');
|
||||
// Load popup with the template info
|
||||
popup.html($("#templatePopupPool").html());
|
||||
// Start Dialog section
|
||||
popup.dialog({
|
||||
title: '_(Add Pool)_',
|
||||
resizable: false,
|
||||
width: 600,
|
||||
modal: true,
|
||||
show : {effect:'fade', duration:250},
|
||||
hide : {effect:'fade', duration:250},
|
||||
buttons: {
|
||||
_(Add)_: function() {
|
||||
var poolname = $(this).find('input[name="poolName"]').val();
|
||||
var valid = /^[a-z_][a-z0-9_-]*[a-z_]$/;
|
||||
var reserved = ['disk','disks','diskP','diskQ','diskR','flash','parity','parity2'];
|
||||
if (reserved.includes(poolname)) {
|
||||
swal({title:'_(Invalid pool name)_',text:'_(Do not use reserved names)_',type:'error',confirmButtonText:'_(Ok)_'});
|
||||
} else if (!valid.test(poolname)) {
|
||||
swal({title:'_(Invalid pool name)_',text:'_(Use lowercase characters only and no ending digits)_',type:'error',confirmButtonText:'_(Ok)_'});
|
||||
} else if (poolname) {
|
||||
$(this).find('form').submit();
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
_(Cancel)_: function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
|
||||
$(".ui-dialog .ui-dialog-title").css('text-align','center').css('width', "100%");
|
||||
$(".ui-dialog .ui-dialog-content").css('padding-top','15px').css('vertical-align','bottom');
|
||||
$(".ui-button-text").css('padding','0px 5px');
|
||||
}
|
||||
|
||||
function pool_status() {
|
||||
$.post('/webGui/include/DeviceList.php',{path:'<?=$path?>',device:'cache'},function(d) {
|
||||
if (!d) return;
|
||||
d = d.split('\0');
|
||||
for (var i=0,data; data=d[i]; i++) {
|
||||
if (data) $('#pool_device'+i).html(data); display_diskio();
|
||||
}
|
||||
<?if ($var['fsState']=='Started'):?>
|
||||
timers.cache_status = setTimeout(cache_status,3000);
|
||||
timers.pool_status = setTimeout(pool_status,3000);
|
||||
<?endif;?>
|
||||
});
|
||||
}
|
||||
@@ -28,22 +81,41 @@ function cache_status() {
|
||||
$('#tab2').bind({click:function() {$('i.toggle').show('slow');}});
|
||||
<?endif;?>
|
||||
|
||||
cache_status();
|
||||
pool_status();
|
||||
</script>
|
||||
|
||||
<table class="disk_status wide">
|
||||
<?foreach ($pools as $pool):?>
|
||||
<?if ($cache[$pool]['devicesSb'] || $var['fsState']=='Stopped'):?>
|
||||
<table class="disk_status wide"<?=$i?' style="margin-top:0"':''?>>
|
||||
<thead><tr><td>_(Device)_</td><td>_(Identification)_</td><td>_(Temp)_.</td><td>_(Reads)_</td><td>_(Writes)_</td><td>_(Errors)_</td><td>_(FS)_</td><td>_(Size)_</td><td>_(Used)_</td><td>_(Free)_</td><td>_(View)_</td></tr></thead>
|
||||
<tbody id="cache_device">
|
||||
<?
|
||||
foreach ($disks as $disk):
|
||||
if ($disk['type']=='Cache') echo "<tr><td colspan='11'> </td></tr>";
|
||||
endforeach;
|
||||
?>
|
||||
<tbody id="pool_device<?=$i++?>">
|
||||
<?foreach ($cache as $disk) if (prefix($disk['name']==$pool)) echo "<tr><td colspan='11'> </td></tr>";?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?endif;?>
|
||||
<?endforeach;?>
|
||||
<?if ($var['fsState']=='Stopped'):?>
|
||||
<input type="button" value="Add Pool" style="margin:0" onclick="addPoolPopup()">
|
||||
<?endif;?>
|
||||
|
||||
<div id="dialogAddPool" style="display:none"></div>
|
||||
<div id="templatePopupPool" style="display:none">
|
||||
<form markdown="1" method="POST" action="/update.htm" target="progressFrame">
|
||||
<input type="hidden" name="changeSlots" value="apply">
|
||||
_(Name)_:
|
||||
: <input type="text" name="poolName" maxlength="40">
|
||||
|
||||
_(Slots)_:
|
||||
: <select name="poolSlots">
|
||||
<?for ($n=1; $n<=$var['MAX_CACHESZ']; $n++):?>
|
||||
<?=mk_option(1,$n,$n)?>
|
||||
<?endfor;?>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
:help3
|
||||
> **Colored Status Indicator** the significance of the color indicator at the beginning of each line in *Cache Devices* is as follows:
|
||||
> **Colored Status Indicator** the significance of the color indicator at the beginning of each line in *Pool Devices* is as follows:
|
||||
>
|
||||
> <i class='fa fa-circle orb green-orb'></i>Normal operation, device is active.
|
||||
>
|
||||
@@ -53,24 +125,24 @@ endforeach;
|
||||
>
|
||||
> <i class='fa fa-square orb grey-orb'></i>No device present, position is empty.
|
||||
>
|
||||
> **Cache** is a device, or device pool, *outside* the Unraid array. It may be exported for network access just
|
||||
> **Pool Devices** is a single device, or pool of multiple devices, *outside* the Unraid array. It may be exported for network access just
|
||||
> like an Array device. Being outside the Unraid array results in significantly faster write access.
|
||||
>
|
||||
> There are two ways to configure the Cache:
|
||||
> There are two ways to configure the Pool devices:
|
||||
>
|
||||
> 1. As a single device, or
|
||||
> 2. As a multi-device pool.
|
||||
>
|
||||
> When configured as a single device you may format the device using any supported file system (btrfs, reiserfs,
|
||||
> or xfs). This configuration offers the highest performance, but at the cost of no data protection - if the
|
||||
> single Cache device fails all data contained on it may be lost.
|
||||
> single pool device fails all data contained on it may be lost.
|
||||
>
|
||||
> When configured as a multi-device pool, Unraid OS will automatically select *btrfs-raid1* format (for both data
|
||||
> and meta-data). btrfs permits any number of devices to be added to the pool and each copy of data is guaranteed
|
||||
> to be written to two different devices. Hence the pool can withstand a single-disk failure without losing data.
|
||||
>
|
||||
> When [User Shares](/Settings/ShareSettings) are enabled, user shares may be configured to
|
||||
> automatically make use of the Cache in order to
|
||||
> automatically make use of the Pool device in order to
|
||||
> speed up writes. A special background process called the *mover* can be scheduled to run
|
||||
> periodically to move user share files off the Cache and onto the Array.
|
||||
:end
|
||||
|
||||
@@ -172,6 +172,9 @@ function data_only($disk) {
|
||||
function cache_only($disk) {
|
||||
return $disk['type']=='Cache';
|
||||
}
|
||||
function prefix($key) {
|
||||
return preg_replace('/[0-9]+$/','',$key);
|
||||
}
|
||||
function array_offline(&$disk) {
|
||||
global $var, $disks;
|
||||
if (strpos($var['mdState'],'ERROR:')===false) {
|
||||
@@ -317,7 +320,7 @@ function show_totals($text,$array) {
|
||||
echo "<td></td>";
|
||||
} else
|
||||
echo "<td colspan=4></td>";
|
||||
echo "</tr>";
|
||||
echo "</tr>\0";
|
||||
}
|
||||
function array_slots() {
|
||||
global $var;
|
||||
@@ -334,18 +337,18 @@ function array_slots() {
|
||||
$out .= "</select></form>";
|
||||
return $out;
|
||||
}
|
||||
function cache_slots($disabled) {
|
||||
function cache_slots($off,$pool,$min,$slots) {
|
||||
global $var;
|
||||
$off = $disabled ? ' disabled' : '';
|
||||
$min = $var['cacheSbNumDisks'];
|
||||
$off = $off && $min ? ' disabled' : '';
|
||||
$max = $var['MAX_CACHESZ'];
|
||||
$out = "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
$out .= "<input type='hidden' name='csrf_token' value='{$var['csrf_token']}'>";
|
||||
$out .= "<input type='hidden' name='changeSlots' value='apply'>";
|
||||
$out .= "<select class='narrow' name='SYS_CACHE_SLOTS' onChange='this.form.submit()'{$off}>";
|
||||
$out .= "<input type='hidden' name='poolName' value='$pool'>";
|
||||
$out .= "<select class='narrow' name='poolSlots' onChange='this.form.submit()'{$off}>";
|
||||
for ($n=$min; $n<=$max; $n++) {
|
||||
$option = $n ?: 'none';
|
||||
$selected = ($n == $var['SYS_CACHE_SLOTS'])? ' selected' : '';
|
||||
$selected = ($n==$slots)? ' selected' : '';
|
||||
$out .= "<option value='$n'{$selected}>$option</option>";
|
||||
}
|
||||
$out .= "</select></form>";
|
||||
@@ -387,22 +390,29 @@ case 'flash':
|
||||
break;
|
||||
case 'cache':
|
||||
$cache = array_filter($disks,'cache_only');
|
||||
$tmp = '/var/tmp/cache_log.tmp';
|
||||
foreach ($cache as $disk) $crypto |= $disk['luksState']!=0 || vfs_luks($disk['fsType']);
|
||||
if ($var['fsState']=='Stopped') {
|
||||
$log = file_exists($tmp) ? parse_ini_file($tmp) : [];
|
||||
$off = false;
|
||||
foreach ($cache as $disk) {
|
||||
array_offline($disk);
|
||||
if (isset($log[$disk['name']])) $off |= ($log[$disk['name']]!=$disk['id']); else $log[$disk['name']] = $disk['id'];
|
||||
$pools = array_unique(array_map('prefix',array_keys($cache)));
|
||||
foreach ($pools as $pool) {
|
||||
$tmp = "/var/tmp/$pool.log.tmp";
|
||||
foreach ($cache as $disk) if (prefix($disk['name'])==$pool) $crypto |= $disk['luksState']!=0 || vfs_luks($disk['fsType']);
|
||||
if ($var['fsState']=='Stopped') {
|
||||
$log = @(array)parse_ini_file($tmp);
|
||||
$off = false;
|
||||
foreach ($cache as $disk) {
|
||||
if (prefix($disk['name'])!=$pool) continue;
|
||||
array_offline($disk);
|
||||
if (isset($log[$disk['name']])) $off |= ($log[$disk['name']]!=$disk['id']); else $log[$disk['name']] = $disk['id'];
|
||||
}
|
||||
$data = []; foreach ($log as $key => $value) $data[] = "$key=\"$value\"";
|
||||
file_put_contents($tmp,implode("\n",$data));
|
||||
echo "<tr class='tr_last'><td>"._('Slots').":</td><td colspan='9'>".cache_slots($off,$pool,$cache[$pool]['devicesSb'],$cache[$pool]['slots'])."</td><td></td></tr>\0";
|
||||
} else {
|
||||
if ($cache[$pool]['devicesSb']) {
|
||||
foreach ($cache as $disk) if (prefix($disk['name'])==$pool) array_online($disk);
|
||||
if ($display['total'] && $var['cacheSbNumDisks']>1) show_totals(sprintf(_('Pool of %s devices'),my_word($cache[$pool]['devicesSb'])),false);
|
||||
echo "\0";
|
||||
}
|
||||
@unlink($tmp);
|
||||
}
|
||||
$data = []; foreach ($log as $key => $value) $data[] = "$key=\"$value\"";
|
||||
file_put_contents($tmp,implode("\n",$data));
|
||||
echo "<tr class='tr_last'><td>"._('Slots').":</td><td colspan='9'>".cache_slots($off)."</td><td></td></tr>";
|
||||
} else {
|
||||
foreach ($cache as $disk) array_online($disk);
|
||||
@unlink($tmp);
|
||||
if ($display['total'] && $var['cacheSbNumDisks']>1) show_totals(sprintf(_('Pool of %s devices'),my_word($var['cacheNumDevices'])),false);
|
||||
}
|
||||
break;
|
||||
case 'open':
|
||||
|
||||
@@ -53,7 +53,7 @@ function my_temp($value) {
|
||||
return is_numeric($value) ? (($unit=='F' ? round(9/5*$value+32) : str_replace('.', $number[0], $value))." $unit") : $value;
|
||||
}
|
||||
function my_disk($name) {
|
||||
return ucfirst(preg_replace('/^(disk|cache|parity)(\d+)/','$1 $2',$name));
|
||||
return ucfirst(preg_replace('/^(.+)(\d+)$/','$1 $2',$name));
|
||||
}
|
||||
function my_disks($disk) {
|
||||
return strpos($disk['status'],'_NP')===false;
|
||||
|
||||
Reference in New Issue
Block a user