mirror of
https://github.com/unraid/webgui.git
synced 2026-05-12 23:30:01 -05:00
Merge remote-tracking branch 'upstream/master' into Fix-zfs-dataset-creation
This commit is contained in:
@@ -1479,6 +1479,20 @@ your client. Be aware that setting a value of -1 will cause the memory footprin
|
||||
files/directories you access via NFS this may or may not lead to out-of-memory conditions.
|
||||
:end
|
||||
|
||||
:nfs_server_max_protocol_help:
|
||||
Select the max NFS Protocol version you want your Unraid server to support.
|
||||
:end
|
||||
|
||||
:nfs_client_max_protocol_help:
|
||||
Select the max NFS Protocol version you want to use to mount your remote shares.
|
||||
:end
|
||||
|
||||
:nfs_threads_help:
|
||||
Set the number of threads for NFS. For light NFS loads, 8 is sufficient. For heaver NFS loads, a higher number of threads might be appropriate.
|
||||
|
||||
If there aren't enough threads, NFS will probably crash.
|
||||
:end
|
||||
|
||||
:shares_enable_disk_help:
|
||||
If set to No, disk shares are unconditionally not exported.
|
||||
|
||||
@@ -1536,6 +1550,10 @@ This will increase write performance but might possibly decrease read performanc
|
||||
*Auto* selects No.
|
||||
:end
|
||||
|
||||
:shares_fuse_file_descriptors_io_help:
|
||||
Set the number of fuse file descriptors. With a lot of file activity on the array, you may need to increase this value.
|
||||
:end
|
||||
|
||||
:syslog_local_server_help:
|
||||
Let the server act as a central syslog server and collect syslog messages from other systems.
|
||||
The server can listen on UDP, TCP or both with a selectable port number.
|
||||
|
||||
@@ -142,12 +142,12 @@ _(Enable container table readmore-js)_:
|
||||
:docker_readmore_help:
|
||||
|
||||
_(Docker Stop Timeout)_ (_(seconds)_):
|
||||
: <input class='narrow' id="DOCKER_TIMEOUT" type="number" name="DOCKER_TIMEOUT" min='1' value="<?=_var($dockercfg,'DOCKER_TIMEOUT')?>">
|
||||
: <input class='narrow' id="DOCKER_TIMEOUT" type="number" name="DOCKER_TIMEOUT" min='1' value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_TIMEOUT'))?>">
|
||||
|
||||
:docker_timeout_help:
|
||||
|
||||
_(Docker PID Limit)_:
|
||||
: <input class='narrow' id="DOCKER_PID_LIMIT" type="number" name="DOCKER_PID_LIMIT" min='1' value="<?=_var($dockercfg,'DOCKER_PID_LIMIT')?>" placeholder="2048">
|
||||
: <input class='narrow' id="DOCKER_PID_LIMIT" type="number" name="DOCKER_PID_LIMIT" min='1' value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_PID_LIMIT'))?>" placeholder="2048">
|
||||
|
||||
:docker_pid_limit_help:
|
||||
|
||||
@@ -164,15 +164,15 @@ _(Docker data-root)_:
|
||||
|
||||
<div markdown="1" id="vdisk_file" style="display:none">
|
||||
_(Docker vDisk size)_:
|
||||
: <input id="DOCKER_IMAGE_SIZE" type="number" name="DOCKER_IMAGE_SIZE" value="<?=_var($dockercfg,'DOCKER_IMAGE_SIZE')?>" class="narrow" required>GB<span id="SIZE_ERROR" class="errortext"></span>
|
||||
: <input id="DOCKER_IMAGE_SIZE" type="number" name="DOCKER_IMAGE_SIZE" value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_SIZE'))?>" class="narrow" required>GB<span id="SIZE_ERROR" class="errortext"></span>
|
||||
|
||||
:docker_vdisk_size_help:
|
||||
|
||||
_(Docker vDisk location)_:
|
||||
: <input type="text" id="DOCKER_IMAGE_FILE1" name="DOCKER_IMAGE_FILE1" autocomplete="off" spellcheck="false" value="<?=_var($dockercfg,'DOCKER_IMAGE_FILE')?>" placeholder="_(e.g.)_ /mnt/user/system/docker.img" data-pickcloseonfile="true" data-pickfilter="img" data-pickroot="/mnt" data-pickfolders="true" disabled required pattern="^[^\\]*(docker-xfs\.img|docker\.img)$">
|
||||
: <input type="text" id="DOCKER_IMAGE_FILE1" name="DOCKER_IMAGE_FILE1" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_FILE'))?>" placeholder="_(e.g.)_ /mnt/user/system/docker.img" data-pickcloseonfile="true" data-pickfilter="img" data-pickroot="/mnt" data-pickfolders="true" disabled required pattern="^[^\\]*(docker-xfs\.img|docker\.img)$">
|
||||
<span class="deleteLabel"><label><input type="checkbox" class="deleteCheckbox"> _(Delete vDisk file)_</label></span>
|
||||
<?if ($var['fsState'] != "Started"):?><span><i class="fa fa-warning icon warning"></i> _(Modify with caution: unable to validate path until Array is Started)_</span>
|
||||
<?elseif (!is_dir(dirname(_var($dockercfg,'DOCKER_IMAGE_FILE')))):?><span class="nonexist"><i class="fa fa-warning icon warning"></i> _(Path does not exist)_</span>
|
||||
<?elseif (!is_dir(dirname(htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_FILE'))))):?><span class="nonexist"><i class="fa fa-warning icon warning"></i> _(Path does not exist)_</span>
|
||||
<?endif;?><span id="IMAGE_ERROR1" class="errortext"></span>
|
||||
|
||||
:docker_vdisk_location_help:
|
||||
@@ -180,7 +180,7 @@ _(Docker vDisk location)_:
|
||||
</div>
|
||||
<div markdown="1" id="vdisk_dir" style="display:none">
|
||||
_(Docker directory)_:
|
||||
: <input type="text" id="DOCKER_IMAGE_FILE2" name="DOCKER_IMAGE_FILE2" autocomplete="off" spellcheck="false" value="<?=_var($dockercfg,'DOCKER_IMAGE_FILE')?>" placeholder="_(e.g.)_ /mnt/user/system/docker" data-pickcloseonfile="true" data-pickfilter="HIDE_FILES_FILTER" data-pickroot="/mnt" data-pickfolders="true" disabled required pattern="^[^\\]*/$">
|
||||
: <input type="text" id="DOCKER_IMAGE_FILE2" name="DOCKER_IMAGE_FILE2" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_FILE'))?>" placeholder="_(e.g.)_ /mnt/user/system/docker" data-pickcloseonfile="true" data-pickfilter="HIDE_FILES_FILTER" data-pickroot="/mnt" data-pickfolders="true" disabled required pattern="^[^\\]*/$">
|
||||
<span class="deleteLabel"><label><input type="checkbox" class="deleteCheckbox"> _(Delete directory)_</label></span>
|
||||
<?if ($var['fsState'] != "Started"):?><span><i class="fa fa-warning icon warning"></i> _(Modify with caution: unable to validate path until Array is Started)_</span>
|
||||
<?elseif (!is_dir(dirname(_var($dockercfg,'DOCKER_IMAGE_FILE')))):?><span class="nonexist"><i class="fa fa-warning icon warning"></i> _(Path does not exist)_</span>
|
||||
@@ -207,7 +207,7 @@ _(Docker storage driver)_:
|
||||
</div>
|
||||
|
||||
_(Default appdata storage location)_:
|
||||
: <input type="text" id="DOCKER_APP_CONFIG_PATH" name="DOCKER_APP_CONFIG_PATH" autocomplete="off" spellcheck="false" value="<?=_var($dockercfg,'DOCKER_APP_CONFIG_PATH')?>" placeholder="_(e.g.)_ /mnt/user/appdata/" data-pickfilter="HIDE_FILES_FILTER" data-pickroot="/mnt" data-pickfolders="true" pattern="^[^\\]*/$">
|
||||
: <input type="text" id="DOCKER_APP_CONFIG_PATH" name="DOCKER_APP_CONFIG_PATH" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($dockercfg,'DOCKER_APP_CONFIG_PATH'))?>" placeholder="_(e.g.)_ /mnt/user/appdata/" data-pickfilter="HIDE_FILES_FILTER" data-pickroot="/mnt" data-pickfolders="true" pattern="^[^\\]*/$">
|
||||
<?if ($var['fsState'] != "Started"):?>
|
||||
<span><i class="fa fa-warning icon warning"></i> _(Modify with caution: unable to validate path until Array is Started)_</span>
|
||||
<?elseif (!is_dir(_var($dockercfg,'DOCKER_APP_CONFIG_PATH'))):?>
|
||||
@@ -354,7 +354,7 @@ _(IPv4 custom network on interface)_ <?=$network?> (_(optional)_):
|
||||
<select id="DOCKER_CUSTOM_<?=$port?>_mask" name="DOCKER_MASK_<?=$port?>" class="mask"<?=$disabled?>>
|
||||
<?for ($m=16; $m<=30; $m++) echo mk_option($mask?:24,$m,$m)?></select>
|
||||
</span>
|
||||
<span class="<?=$gw4class?>">**_(Gateway)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_gw" name="DOCKER_GATEWAY_<?=$port?>" class="ip4" value="<?=_var($dockercfg,"DOCKER_GATEWAY_$port")?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>></span>
|
||||
<span class="<?=$gw4class?>">**_(Gateway)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_gw" name="DOCKER_GATEWAY_<?=$port?>" class="ip4" value="<?=htmlspecialchars(_var($dockercfg,"DOCKER_GATEWAY_$port"))?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>></span>
|
||||
<input type="checkbox" id="DOCKER_CUSTOM_<?=$port?>_dhcp" onchange="customDHCP(this.id,4)"<?=$subnet?'checked':''?><?=$dhcpDisabled?>>
|
||||
**_(DHCP pool)_:** <input type="text" id="DOCKER_CUSTOM_<?=$port?>_pool" name="DOCKER_RANGE_<?=$port?>" class="ip4" value="<?=$range?>" title="_(IPv4 address A.B.C.D)_"<?=$disabled?>>/
|
||||
<select id="DOCKER_CUSTOM_<?=$port?>_size" name="DOCKER_SIZE_<?=$port?>" class="mask" onchange="changeHosts(this.id,this.value)"<?=$disabled?>>
|
||||
@@ -421,7 +421,7 @@ _(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
|
||||
<span class="ip6">**_(Subnet)_:**<input type="text" id="DOCKER_CUSTOM6_<?=$port?>_net" name="DOCKER_SUBNET6_<?=$port?>" class="ip6" value="<?=$subnet6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_"<?=$disabled?>>/
|
||||
<select id="DOCKER_CUSTOM6_<?=$port?>_mask" name="DOCKER_MASK6_<?=$port?>" class="mask"<?=$disabled?>>
|
||||
<?for ($m=64; $m<=120; $m+=8) echo mk_option($mask6?:64,$m,$m)?></select></span>
|
||||
<span class="gw6">**_(Gateway)_:**<input type="text" id="DOCKER_CUSTOM6_<?=$port?>_gw" name="DOCKER_GATEWAY6_<?=$port?>" class="gw6" value="<?=_var($dockercfg,"DOCKER_GATEWAY6_$port")?>" title="_(IPv6 address nnnn:xxxx::yyyy)_"<?=$disabled?>></span>
|
||||
<span class="gw6">**_(Gateway)_:**<input type="text" id="DOCKER_CUSTOM6_<?=$port?>_gw" name="DOCKER_GATEWAY6_<?=$port?>" class="gw6" value="<?=htmlspecialchars(_var($dockercfg,"DOCKER_GATEWAY6_$port"))?>" title="_(IPv6 address nnnn:xxxx::yyyy)_"<?=$disabled?>></span>
|
||||
<input type="checkbox" id="DOCKER_CUSTOM6_<?=$port?>_dhcp" onchange="customDHCP(this.id,6)"<?=$subnet6?'checked':''?><?=$dhcpDisabled?>>
|
||||
**_(DHCP pool)_:**<input type="text" id="DOCKER_CUSTOM6_<?=$port?>_pool" name="DOCKER_RANGE6_<?=$port?>" class="ip6" value="<?=$range6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_"<?=$disabled?>>/
|
||||
<select id="DOCKER_CUSTOM6_<?=$port?>_size" name="DOCKER_SIZE6_<?=$port?>" class="mask"<?=$disabled?>>
|
||||
@@ -444,21 +444,21 @@ _(Docker version)_:
|
||||
|
||||
<?if (_var($dockercfg,'DOCKER_IMAGE_TYPE')!='folder'):?>
|
||||
_(Docker vDisk location)_:
|
||||
: <?=_var($dockercfg,'DOCKER_IMAGE_FILE')?>
|
||||
: <?=htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_FILE'))?>
|
||||
<?else:?>
|
||||
_(Docker directory)_:
|
||||
: <?=_var($dockercfg,'DOCKER_IMAGE_FILE')?>
|
||||
: <?=htmlspecialchars(_var($dockercfg,'DOCKER_IMAGE_FILE'))?>
|
||||
<?endif;?>
|
||||
|
||||
:docker_vdisk_location_active_help:
|
||||
|
||||
_(Docker storage driver)_:
|
||||
: <?=_var($dockercfg,'DOCKER_BACKINGFS')?>
|
||||
: <?=htmlspecialchars(_var($dockercfg,'DOCKER_BACKINGFS'))?>
|
||||
|
||||
:docker_storage_driver_active_help:
|
||||
|
||||
_(Default appdata storage location)_:
|
||||
: <?=_var($dockercfg,'DOCKER_APP_CONFIG_PATH')?>
|
||||
: <?=htmlspecialchars(_var($dockercfg,'DOCKER_APP_CONFIG_PATH'))?>
|
||||
|
||||
:docker_appdata_location_active_help:
|
||||
|
||||
|
||||
@@ -447,7 +447,7 @@ if (!empty($TS_no_peers) && !empty($TS_container)) {
|
||||
}
|
||||
// Construct WebUI URL on container template page
|
||||
// Check if webui_url, Tailscale WebUI and MagicDNS are not empty and make sure that MagicDNS is enabled
|
||||
if (!empty($webui_url) && !empty($xml['TailscaleWebUI']) && (!empty($TS_no_peers['CurrentTailnet']['MagicDNSEnabled']) || $TS_no_peers['CurrentTailnet']['MagicDNSEnabled'])) {
|
||||
if ( !empty($webui_url) && !empty($xml['TailscaleWebUI']) && (!empty($TS_no_peers['CurrentTailnet']['MagicDNSEnabled']) || ($TS_no_peers['CurrentTailnet']['MagicDNSEnabled']??false))) {
|
||||
// Check if serve or funnel are enabled by checking for [hostname] and replace string with TS_DNSName
|
||||
if (!empty($xml['TailscaleWebUI']) && strpos($xml['TailscaleWebUI'], '[hostname]') !== false && isset($TS_DNSName)) {
|
||||
$TS_webui_url = str_replace("[hostname][magicdns]", rtrim($TS_DNSName, '.'), $xml['TailscaleWebUI']);
|
||||
@@ -1145,7 +1145,7 @@ _(Container Network)_:
|
||||
<?if (!file_exists('/usr/local/sbin/tailscale')):?>
|
||||
<div markdown="1" class="TSdeploy noshow">
|
||||
<b>_(Recommendation)_</b>:
|
||||
: <p>_(For the best experience with Tailscale, install "Tailscale (Plugin)" from)_ <a href="/Apps" target='_blank'> Community Applications</a>.</p>
|
||||
: <p>_(For the best experience with Tailscale, install "Tailscale (Plugin)" from)_ <a href="/Apps?search=Tailscale%20(Plugin)" target='_blank'> Community Applications</a>.</p>
|
||||
</div>
|
||||
<?endif;?>
|
||||
|
||||
@@ -1335,7 +1335,7 @@ _(Tailscale WebUI)_:
|
||||
|
||||
<div markdown="1" class="TSroutes noshow">
|
||||
_(Tailscale Advertise Routes)_:
|
||||
: <input type="text" pattern="[0-9:., ]*" name="TSroutes" <?php if (!empty($xml['TailscaleRoutes'])) echo 'value="' . $xml['TailscaleRoutes'] . '"'?> placeholder="_(Leave empty if unsure)_">
|
||||
: <input type="text" pattern="[0-9:., \/]*" name="TSroutes" <?php if (!empty($xml['TailscaleRoutes'])) echo 'value="' . $xml['TailscaleRoutes'] . '"'?> placeholder="_(Leave empty if unsure)_">
|
||||
|
||||
:docker_tailscale_advertise_routes_help:
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ foreach ($containers as $ct) {
|
||||
$TS_version = explode('-', $TSstats["Version"])[0];
|
||||
if (!empty($TS_version)) {
|
||||
if (!empty($TS_latest_version)) {
|
||||
if ($TS_version !== $TS_latest_version) {
|
||||
if (version_compare($TS_version, $TS_latest_version, '<')) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Tailscale:")."</span><span class='ui-tailscale-value'>v" . $TS_version . " ➔ v" . $TS_latest_version . " "._("available!")."</span></div>";
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Tailscale:")."</span><span class='ui-tailscale-value'>v" . $TS_version . "</span></div>";
|
||||
|
||||
@@ -307,11 +307,9 @@ function xmlSecurity(&$template) {
|
||||
xmlSecurity($element);
|
||||
} else {
|
||||
if (is_string($element)) {
|
||||
$tempElement = htmlspecialchars_decode($element);
|
||||
$tempElement = str_replace("[","<",$tempElement);
|
||||
$tempElement = str_replace("]",">",$tempElement);
|
||||
if (preg_match('#<script(.*?)>(.*?)</script>#is',$tempElement) || preg_match('#<iframe(.*?)>(.*?)</iframe>#is',$tempElement) || (stripos($tempElement,"<link") !== false) ) {
|
||||
$element = "REMOVED";
|
||||
$tempElement = htmlspecialchars_decode($element??"");
|
||||
if ( trim(strip_tags($tempElement)) !== trim($tempElement) ) {
|
||||
$element = str_replace(["<",">"],["",""],$tempElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,8 +406,14 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
$TS_routes = !empty($xml['TailscaleRoutes']) ? '-e TAILSCALE_ADVERTISE_ROUTES=' . escapeshellarg($xml['TailscaleRoutes']) : '';
|
||||
$TS_accept_routes = !empty($xml['TailscaleAcceptRoutes']) && $xml['TailscaleAcceptRoutes'] === 'true' ? '-e TAILSCALE_ACCEPT_ROUTES=true' : '';
|
||||
if (!empty($xml['PostArgs'])) {
|
||||
$TS_postargs = '-e ORG_POSTARGS=' . escapeshellarg($xml['PostArgs']);
|
||||
$xml['PostArgs'] = '';
|
||||
$split_PostArgs = strpos($xml['PostArgs'], ';');
|
||||
if ($split_PostArgs !== false) {
|
||||
$TS_postargs = !empty(substr($xml['PostArgs'], 0, $split_PostArgs)) ? '-e ORG_POSTARGS=' . escapeshellarg(substr($xml['PostArgs'], 0, $split_PostArgs)) : '';
|
||||
$xml['PostArgs'] = ';' . substr($xml['PostArgs'], $split_PostArgs + 1);
|
||||
} else {
|
||||
$TS_postargs = '-e ORG_POSTARGS=' . escapeshellarg($xml['PostArgs']);
|
||||
$xml['PostArgs'] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ function addDockerContainerContext(container, image, template, started, paused,
|
||||
opts.push({divider:true});
|
||||
opts.push({text:_('Donate'),icon:'fa-external-link', href:donateLink,target:'_blank'});
|
||||
}
|
||||
context.destroy('#'+id);
|
||||
context.attach('#'+id, opts);
|
||||
}
|
||||
function addDockerImageContext(image, imageTag) {
|
||||
|
||||
-28
File diff suppressed because one or more lines are too long
+28
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
||||
{
|
||||
".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs": {
|
||||
"file": "_nuxt/unraid-components.client-CQOXNcK4.js",
|
||||
"file": "_nuxt/unraid-components.client-DaXtPGYC.js",
|
||||
"name": "unraid-components.client",
|
||||
"src": ".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs",
|
||||
"isEntry": true,
|
||||
@@ -8,5 +8,5 @@
|
||||
"_nuxt/unraid-components-p_3YF86n.css"
|
||||
]
|
||||
},
|
||||
"ts": 1723595088
|
||||
"ts": 1736299175
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
Menu="VMs:0"
|
||||
Title="VM Usage Statisics"
|
||||
Title="VM Usage Statistics"
|
||||
Nchan="vm_usage:stop"
|
||||
Cond="exec(\"grep -o '^USAGE=.Y' /boot/config/domain.cfg 2>/dev/null\") && is_file('/var/run/libvirt/libvirtd.pid')"
|
||||
---
|
||||
|
||||
@@ -150,7 +150,9 @@ case 'domain-start-consoleRV':
|
||||
$vvarray = array() ;
|
||||
$vvarray[] = "[virt-viewer]\n";
|
||||
$vvarray[] = "type=$protocol\n";
|
||||
$vvarray[] = "host="._var($_SERVER,'HTTP_HOST')."\n" ;
|
||||
$vvarrayhost = _var($_SERVER,'HTTP_HOST');
|
||||
if (strpos($vvarrayhost,":")) $vvarrayhost = parse_url($vvarrayhost,PHP_URL_HOST);
|
||||
$vvarray[] = "host=$vvarrayhost\n" ;
|
||||
$vvarray[] = "port=$port\n" ;
|
||||
$vvarray[] = "delete-this-file=1\n" ;
|
||||
if (!is_dir("/mnt/user/system/remoteviewer")) mkdir("/mnt/user/system/remoteviewer") ;
|
||||
@@ -183,7 +185,9 @@ case 'domain-consoleRV':
|
||||
$vvarray = array() ;
|
||||
$vvarray[] = "[virt-viewer]\n";
|
||||
$vvarray[] = "type=$protocol\n";
|
||||
$vvarray[] = "host="._var($_SERVER,'HTTP_HOST')."\n" ;
|
||||
$vvarrayhost = _var($_SERVER,'HTTP_HOST');
|
||||
if (strpos($vvarrayhost,":")) $vvarrayhost = parse_url($vvarrayhost,PHP_URL_HOST);
|
||||
$vvarray[] = "host=$vvarrayhost\n" ;
|
||||
$vvarray[] = "port=$port\n" ;
|
||||
$vvarray[] = "delete-this-file=1\n" ;
|
||||
if (!is_dir("/mnt/user/system/remoteviewer")) mkdir("/mnt/user/system/remoteviewer") ;
|
||||
|
||||
@@ -239,7 +239,7 @@ function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, f
|
||||
}});
|
||||
}
|
||||
}
|
||||
if (usage) context.attach('#vmusage-'+uuid, opts); else context.attach('#vm-'+uuid, opts);
|
||||
if (usage) { context.destroy('#vmusage-'+uuid); context.attach('#vmusage-'+uuid, opts); } else { context.destroy('#vm-'+uuid); context.attach('#vm-'+uuid, opts); }
|
||||
}
|
||||
function addVMSnapContext(name, uuid, template, state, snapshotname, method){
|
||||
var opts = [];
|
||||
@@ -273,6 +273,7 @@ function addVMSnapContext(name, uuid, template, state, snapshotname, method){
|
||||
$('#vm-'+uuid).find('i').removeClass('fa-play fa-square fa-pause').addClass('fa-refresh fa-spin');
|
||||
selectsnapshot(uuid, name, snapshotname, "remove",true) ;
|
||||
}});
|
||||
context.destroy('#vmsnap-'+uuid);
|
||||
context.attach('#vmsnap-'+uuid, opts);
|
||||
}
|
||||
function startAll() {
|
||||
|
||||
@@ -77,11 +77,11 @@ while (true) {
|
||||
$echodata .= "<tr><td>$vm</td>" ;
|
||||
$echodata .= "<td class='advanced'><span class='cpug-".$vm."'>".$vmdata['cpuguest']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuguest']."%;'> </span><span></span></div></td>";
|
||||
$echodata .= "<td class='advanced'><span class='cpuh-".$vm."'>".$vmdata['cpuhost']."%</span><div class='usage-disk mm'><span id='cpuh-".$vm."' style='width:".$vmdata['cpuhost']."%;'> </span><span></span></div></td><td>";
|
||||
$echodata .= my_scale($vmdata['mem']*1024,$unit)."$unit / ".my_scale($vmdata['curmem']*1024,$unit)."$unit";
|
||||
$echodata .= my_scale($vmdata['mem']*1024,$unit,null,null,1024)."$unit / ".my_scale($vmdata['curmem']*1024,$unit,null,null,1024)."$unit";
|
||||
if ($vmdata['curmem'] === $vmdata['maxmem']) $echodata .= " </td><td>";
|
||||
else $echodata .= " / " .my_scale($vmdata['maxmem']*1024,$unit)."$unit </td><td>";
|
||||
$echodata .= _("Read").": ".my_scale($vmdata['rdrate']/$timer,$unit)."$unit/s<br>"._("Write").": ".my_scale($vmdata['wrrate']/$timer,$unit)."$unit/s</td><td>";
|
||||
$echodata .= _("RX").": ".my_scale($vmdata['rxrate']/$timer,$unit)."$unit/s<br>"._("TX").": ".my_scale($vmdata['txrate']/$timer,$unit)."$unit/s</td></tr>";
|
||||
else $echodata .= " / " .my_scale($vmdata['maxmem']*1024,$unit,null,null,1024)."$unit </td><td>";
|
||||
$echodata .= _("Read").": ".my_scale($vmdata['rdrate']/$timer,$unit,null,null,1024)."$unit/s<br>"._("Write").": ".my_scale($vmdata['wrrate']/$timer,$unit,null,null,1024)."$unit/s</td><td>";
|
||||
$echodata .= _("RX").": ".my_scale($vmdata['rxrate']/$timer,$unit,null,null,1024)."$unit/s<br>"._("TX").": ".my_scale($vmdata['txrate']/$timer,$unit,null,null,1024)."$unit/s</td></tr>";
|
||||
}
|
||||
$echo = $echodata ;
|
||||
}
|
||||
|
||||
@@ -866,7 +866,7 @@
|
||||
_(Boot Order)_:
|
||||
<input type="number" size="5" maxlength="5" id="disk[<?=$i?>][boot]" class="narrow bootorder" style="width: 50px;" name="disk[<?=$i?>][boot]" title="_(Boot order)_" value="<?=$arrDisk['boot']?>" >
|
||||
_(Discard)_:
|
||||
<select name="disk[<?=$i?>][discard]" class="disk_driver narrow" title="_(Set discard option)_">
|
||||
<select name="disk[<?=$i?>][discard]" class="narrow" title="_(Set discard option)_">
|
||||
<?mk_dropdown_options($arrValidDiskDiscard, $arrDisk['discard']);?>
|
||||
</select>
|
||||
<? if ($arrDisk['bus'] == "virtio" || $arrDisk['bus'] == "usb") $ssddisabled = "hidden "; else $ssddisabled = " ";?>
|
||||
@@ -1029,7 +1029,7 @@
|
||||
_(Boot Order)_:
|
||||
<input type="number" size="5" maxlength="5" id="disk[{{INDEX}}][boot]" class="narrow bootorder" style="width: 50px;" name="disk[{{INDEX}}][boot]" title="_(Boot order)_" value="" >
|
||||
_(Discard)_:
|
||||
<select name="disk[{{INDEX}}][discard]" class="disk_driver narrow" title="_(Set discard option)_">
|
||||
<select name="disk[{{INDEX}}][discard]" class="narrow" title="_(Set discard option)_">
|
||||
<?mk_dropdown_options($arrValidDiskDiscard, "unmap");?>
|
||||
</select>
|
||||
<span id="disk[{{INDEX}}][rotatetext]" hidden>_(SSD)_:</span>
|
||||
@@ -2562,13 +2562,13 @@ $(function() {
|
||||
$button.val($button.attr('busyvalue'));
|
||||
|
||||
swal({
|
||||
title: _("Template Name")_,
|
||||
text: _("Enter name:\nIf name already exists it will be replaced.")_,
|
||||
title: '_(Template Name)_',
|
||||
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
|
||||
type: "input",
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false,
|
||||
//animation: "slide-from-top",
|
||||
inputPlaceholder: _("Leaving blank will use OS name.")_
|
||||
inputPlaceholder: "_(Leaving blank will use OS name.)_"
|
||||
},
|
||||
function(inputValue){
|
||||
|
||||
@@ -2643,13 +2643,13 @@ $(function() {
|
||||
$button.val($button.attr('busyvalue'));
|
||||
|
||||
swal({
|
||||
title: _("Template Name")_,
|
||||
text: _("Enter name:\nIf name already exists it will be replaced.")_,
|
||||
title: "_(Template Name)_",
|
||||
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
|
||||
type: "input",
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false,
|
||||
//animation: "slide-from-top",
|
||||
inputPlaceholder: _("Leaving blank will use OS name.")_
|
||||
inputPlaceholder: "_(Leaving blank will use OS name.)_"
|
||||
},
|
||||
function(inputValue){
|
||||
|
||||
|
||||
@@ -216,13 +216,13 @@ $(function() {
|
||||
$form.find('input').prop('disabled', true);
|
||||
$button.val($button.attr('busyvalue'));
|
||||
swal({
|
||||
title: _("Template Name")_,
|
||||
text: _("Enter name:\nIf name already exists it will be replaced.")_,
|
||||
title: "_(Template Name)_",
|
||||
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
|
||||
type: "input",
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false,
|
||||
//animation: "slide-from-top",
|
||||
inputPlaceholder: _("Leaving blank will use OS name.")_
|
||||
inputPlaceholder: "_(Leaving blank will use OS name.)_"
|
||||
},
|
||||
function(inputValue){
|
||||
postdata=postdata+"&templatename="+inputValue;
|
||||
|
||||
@@ -201,7 +201,7 @@ switch ($theme) {
|
||||
<table id='db-box1' class='dashboard'>
|
||||
<tbody class='system'>
|
||||
<tr><td><i class='icon-performance f32'></i><div class='section'><?=_var($var,'NAME')?><br>
|
||||
<span><?=_var($var,'COMMENT')?></span><span id="current_time_" class="switch head_time"></span><br></div>
|
||||
<span><?=htmlspecialchars(_var($var,'COMMENT'))?></span><span id="current_time_" class="switch head_time"></span><br></div>
|
||||
<a href='/Dashboard/Settings/Identification'><i class='fa fa-fw fa-cog control' title="_(Go to identification settings)_"></i></a><i class='fa fa-fw fa-wrench control tile' onclick='contentMgmt()' title="_(Tile Management)_"></i>
|
||||
<span class='ctrl'>
|
||||
<?if ($parity||$mover||$btrfs):?>
|
||||
@@ -216,7 +216,7 @@ switch ($theme) {
|
||||
<tr><td>
|
||||
<div class='leftside'>
|
||||
<a href="/Settings/DateTime" class="hand none"><span id="current_time"></span></a><br><span id="current_date"></span><br><br>
|
||||
<span class='header'><i class='indent fa fa-file-text-o'></i>_(Model)_</span><br><i class='indent'></i><?=_var($var,'SYS_MODEL')?:'---'?><br><br>
|
||||
<span class='header'><i class='indent fa fa-file-text-o'></i>_(Model)_</span><br><i class='indent'></i><?=htmlspecialchars(_var($var,'SYS_MODEL'))?:'---'?><br><br>
|
||||
<span class='header'><i class='indent fa fa-id-badge'></i>_(Registration)_</span><br><i class='indent'></i>Unraid OS <b><em><?=_var($var,'regTy')?></em></b><br><br>
|
||||
<span class='header'><i class='indent fa fa-clock-o'></i>_(Uptime)_</span><br><i class='indent'></i><span class='uptime'></span>
|
||||
</div>
|
||||
@@ -464,10 +464,10 @@ if (_var($var,'shareSMBEnabled')=='yes') {
|
||||
$list = "<a href=\"/Dashboard/Shares/Share?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
if ($share['luksStatus']>0) $list = str_replace('blue-text','green-text',$list);
|
||||
elseif ($share['useCache']=='only') $list = str_replace('blue-text','orange-text',$list);
|
||||
$comment = $share['comment'] ?: ' ';
|
||||
$comment = $share['comment'] ?: '-';
|
||||
$security = export_settings(_var($var,'shareSMBEnabled'), $sec[$name]);
|
||||
$last = $name==array_key_last($shares) ? ' last' : '';
|
||||
echo "<tr class='smb share share1{$last}'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>$comment</span><span class='w18'>$security</span><span id='share",$i++,"'>0</span></td></tr>";
|
||||
echo "<tr class='smb share share1{$last}'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>".htmlspecialchars($comment)."</span><span class='w18'>$security</span><span id='share",$i++,"'>0</span></td></tr>";
|
||||
}
|
||||
if (!count($shares)) echo "<tr class='smb share share1'><td class='none'>"._("No shares present")."</td></tr>";
|
||||
}
|
||||
@@ -476,10 +476,10 @@ if (_var($var,'shareNFSEnabled')=='yes') {
|
||||
$list = "<a href=\"/Dashboard/Shares/Share?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
if ($share['luksStatus']>0) $list = str_replace('blue-text','green-text',$list);
|
||||
elseif ($share['useCache']=='only') $list = str_replace('blue-text','orange-text',$list);
|
||||
$comment = $share['comment'] ?: ' ';
|
||||
$comment = $share['comment'] ?: '-';
|
||||
$security = export_settings(_var($var,'shareNFSEnabled'), $sec_nfs[$name]);
|
||||
$last = $name==array_key_last($shares) ? ' last' : '';
|
||||
echo "<tr class='nfs share share3{$last}'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>$comment</span><span class='w18'>$security</span><span>-</span></td></tr>";
|
||||
echo "<tr class='nfs share share3{$last}'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>".htmlspecialchars($comment)."</span><span class='w18'>$security</span><span>-</span></td></tr>";
|
||||
}
|
||||
if (!count($shares)) echo "<tr class='nfs share share3'><td class='none'>"._("No shares present")."</td></tr>";
|
||||
}
|
||||
@@ -488,8 +488,8 @@ if (!$group) {
|
||||
$list = "<a href=\"/Dashboard/Shares/Share?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
if ($share['luksStatus']>0) $list = str_replace('blue-text','green-text',$list);
|
||||
elseif ($share['useCache']=='only') $list = str_replace('blue-text','orange-text',$list);
|
||||
$comment = $share['comment'] ?: ' ';
|
||||
echo "<tr class='share'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>$comment</span><span class='w18'>-</span><span>-</span></td></tr>";
|
||||
$comment = $share['comment'] ?: '-';
|
||||
echo "<tr class='share'><td><span class='w26'><i class='icon-folder f14'></i>$list</span><span class='w44'>".htmlspecialchars($comment)."</span><span class='w18'>-</span><span>-</span></td></tr>";
|
||||
}
|
||||
if (!count($shares)) echo "<tr class='share'><td class='none'>"._("No shares present")."</td></tr>";
|
||||
}
|
||||
@@ -519,7 +519,7 @@ if (_var($var,'shareSMBEnabled')=='yes') {
|
||||
foreach ($users as $user) {
|
||||
$name = $user['name'];
|
||||
$list = "<a href=\"/Dashboard/Users/UserEdit?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
$desc = $user['desc'] ?: ' ';
|
||||
$desc = $user['desc'] ?: '-';
|
||||
if ($name=='root') {
|
||||
$write = $read = '-';
|
||||
} else {
|
||||
@@ -544,27 +544,27 @@ if (_var($var,'shareSMBEnabled')=='yes') {
|
||||
}
|
||||
if ($user['passwd']!='yes') $list = str_replace('blue-text','orange-text',$list);
|
||||
$last = $name==array_key_last($users) ? ' last' : '';
|
||||
echo "<tr class='smb user user1{$last}'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>$desc</span><span class='w18'>$write</span><span>$read</span></td></tr>";
|
||||
echo "<tr class='smb user user1{$last}'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>".htmlspecialchars($desc)."</span><span class='w18'>$write</span><span>$read</span></td></tr>";
|
||||
}
|
||||
}
|
||||
if (_var($var,'shareNFSEnabled')=='yes') {
|
||||
foreach ($users as $user) {
|
||||
$name = $user['name'];
|
||||
$list = "<a href=\"/Dashboard/Users/UserEdit?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
$desc = $user['desc'] ?: ' ';
|
||||
$desc = $user['desc'] ?: '-';
|
||||
$write = '-'; $read = '-';
|
||||
if ($user['passwd']!='yes') $list = str_replace('blue-text','orange-text',$list);
|
||||
$last = $name==array_key_last($users) ? ' last' : '';
|
||||
echo "<tr class='nfs user user3{$last}'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>$desc</span><span class='w18'>$write</span><span>$read</span></td></tr>";
|
||||
echo "<tr class='nfs user user3{$last}'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>".htmlspecialchars($desc)."</span><span class='w18'>$write</span><span>$read</span></td></tr>";
|
||||
}
|
||||
}
|
||||
if (!$group) {
|
||||
foreach ($users as $user) {
|
||||
$name = $user['name'];
|
||||
$list = "<a href=\"/Dashboard/Users/UserEdit?name=".urlencode($name)."\" class=\"blue-text\" title=\"$name settings\">$name</a>";
|
||||
$desc = $user['desc'] ?: ' ';
|
||||
$desc = $user['desc'] ?: '-';
|
||||
if ($user['passwd']!='yes') $list = str_replace('blue-text','orange-text',$list);
|
||||
echo "<tr class='user'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>$desc</span><span class='w18'>-</span><span>-</span></td></tr>";
|
||||
echo "<tr class='user'><td><span class='w26'><i class='icon-user f14'></i>$list</span><span class='w44'>".htmlspecialchars($desc)."</span><span class='w18'>-</span><span>-</span></td></tr>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1033,6 +1033,7 @@ function smartMenu(table) {
|
||||
opts.push({text:"_(Acknowledge)_",icon:'fa-check-square-o',action:function(e){e.preventDefault();acknowledge(id,disk);}});
|
||||
}
|
||||
$(id).bind('click',function(){update2=false;}).bind('mouseout',function(){setTimeout(function(){update2=true;},15000);});
|
||||
context.destroy(id);
|
||||
context.attach(id,opts);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Menu="Device New"
|
||||
Title="Attributes"
|
||||
Tag="address-card-o"
|
||||
Cond="strpos(_var($disks[$name],'status'),'_NP')===false"
|
||||
Cond="array_key_exists($name, $disks) || array_key_exists($name, $devs)"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Menu="Device New"
|
||||
Title="Capabilities"
|
||||
Tag="building"
|
||||
Cond="strpos(_var($disks[$name],'status'),'_NP')===false"
|
||||
Cond="array_key_exists($name, $disks) || array_key_exists($name, $devs)"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Menu="Device New"
|
||||
Title="Identity"
|
||||
Tag="user"
|
||||
Cond="strpos(_var($disks[$name],'status'),'_NP')===false"
|
||||
Cond="array_key_exists($name, $disks) || array_key_exists($name, $devs)"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
Menu="Device:1"
|
||||
Title="$name _(Settings)_"
|
||||
Tag="hdd-o"
|
||||
Cond="array_key_exists($name, $disks) || array_key_exists($name, $devs)"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
@@ -622,13 +623,13 @@ function renamePoolPopup() {
|
||||
});
|
||||
dialogStyle();
|
||||
}
|
||||
function eraseDisk(name) {
|
||||
function eraseDisk() {
|
||||
swal({
|
||||
title:"_(Erase Device Content)_?",
|
||||
text:"<?=$textErase?><p style='font-weight:bold;color:red;margin:8px 0'>_(Existing content is permanently lost)_</p>",
|
||||
html:true,
|
||||
type:'input',
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),$name)?>",
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),htmlspecialchars($name))?>",
|
||||
showCancelButton:true,
|
||||
closeOnConfirm:false,
|
||||
confirmButtonText:"_(Proceed)_",
|
||||
@@ -641,7 +642,7 @@ function eraseDisk(name) {
|
||||
$('#eraseButton').prop('disabled',true);
|
||||
$('#removeButton').prop('disabled',true);
|
||||
$('div.spinner.fixed').show();
|
||||
$.post("/update.htm",{cmdWipefs:name},function(){
|
||||
$.post("/update.htm",{cmdWipefs:"<?=$name?>"},function(){
|
||||
$('div.spinner.fixed').hide();
|
||||
refresh();
|
||||
});
|
||||
@@ -650,13 +651,13 @@ function eraseDisk(name) {
|
||||
}
|
||||
});
|
||||
}
|
||||
function removePool(name) {
|
||||
function removePool() {
|
||||
swal({
|
||||
title:"_(Remove pool)_?",
|
||||
text:"<?=$textDelete?>",
|
||||
html:true,
|
||||
type:'input',
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),$name)?>",
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),htmlspecialchars($name))?>",
|
||||
showCancelButton:true,
|
||||
closeOnConfirm:false,
|
||||
confirmButtonText:"_(Proceed)_",
|
||||
@@ -669,22 +670,22 @@ function removePool(name) {
|
||||
$('#eraseButton').prop('disabled',true);
|
||||
$('#removeButton').prop('disabled',true);
|
||||
$('div.spinner.fixed').show();
|
||||
$.post("/update.htm",{changeSlots:"apply",poolName:name,poolSlots:0},function(){
|
||||
$.post("/update.htm",{changeSlots:"apply",poolName:"<?=$name?>",poolSlots:0},function(){
|
||||
$('div.spinner.fixed').hide();
|
||||
refresh();
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
if (confirm.length) swal({title:"_(Incorrect confirmation)_",text:"_(Please try again)_!",type:'error',html:true,confirmButtonText:"_(Ok)_"});
|
||||
}
|
||||
});
|
||||
}
|
||||
function upgradeZpool(name) {
|
||||
function upgradeZpool() {
|
||||
swal({
|
||||
title:"_(Upgrade ZFS Pool)_?",
|
||||
text:"_(This operation cannot be reversed)_. _(After upgrading the volume may not be mountable in previous versions of Unraid)_.<p style='font-weight:bold;color:red;margin:8px 0'>_(The ZFS volume will be upgraded)_</p>",
|
||||
html:true,
|
||||
type:'input',
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),$name)?>",
|
||||
inputPlaceholder:"<?=sprintf(_('To confirm type: %s'),htmlspecialchars($name))?>",
|
||||
showCancelButton:true,
|
||||
closeOnConfirm:false,
|
||||
confirmButtonText:"_(Proceed)_",
|
||||
@@ -697,7 +698,7 @@ function upgradeZpool(name) {
|
||||
$('#eraseButton').prop('disabled',true);
|
||||
$('#deleteButton').prop('disabled',true);
|
||||
$('div.spinner.fixed').show();
|
||||
$.post("/webGui/include/zfs_upgrade.php",{name:name},function(){
|
||||
$.post("/webGui/include/zfs_upgrade.php",{name:"<?=$name?>"},function(){
|
||||
$('div.spinner.fixed').hide();
|
||||
refresh();
|
||||
});
|
||||
@@ -711,11 +712,11 @@ function upgradeZpool(name) {
|
||||
<form markdown="1" method="POST" action="/update.htm" target="progressFrame" onsubmit="setFloor()">
|
||||
<?if (_var($var,'fsState')=="Stopped" && isPool($name) && !isSubpool($name)):?>
|
||||
_(Name)_:
|
||||
: <a onclick="renamePoolPopup()" style="cursor:pointer" title="_(Rename Pool)_"><?=$name?></a>
|
||||
: <a onclick="renamePoolPopup()" style="cursor:pointer" title="_(Rename Pool)_"><?=htmlspecialchars($name)?></a>
|
||||
|
||||
<?else:?>
|
||||
_(Name)_:
|
||||
: <?=_(my_disk(native($name)),3)?>
|
||||
: <?=_(my_disk(native(htmlspecialchars($name))),3)?>
|
||||
|
||||
<?endif;?>
|
||||
<?if (diskStatus('_NP')):?>
|
||||
@@ -849,13 +850,13 @@ _(Critical disk utilization threshold)_ (%):
|
||||
<?if (diskType('Parity','Data')):?>
|
||||
<?if (_var($var,'fsState')=="Stopped" && diskStatus('_NEW')): $erasable=true; endif;?>
|
||||
<?if (_var($var,'fsState')=="Started" && _var($var,'startMode')!="Normal" && diskType('Data')): $erasable=true; endif;?>
|
||||
<input type="button" id="eraseButton" value="_(Erase)_" onclick="eraseDisk('<?=$name?>')"<?=$erasable?'':' disabled'?>>
|
||||
<input type="button" id="eraseButton" value="_(Erase)_" onclick="eraseDisk()"<?=$erasable?'':' disabled'?>>
|
||||
<?endif;?>
|
||||
<?if (isPool($name) && isSubpool($name)===false):?>
|
||||
<?if (_var($var,'fsState')=="Stopped" || (_var($var,'fsState')=="Started" && _var($var,'startMode')!="Normal")): $erasable=true; endif;?>
|
||||
<input type="button" id="eraseButton" value="_(Erase Pool)_" onclick="eraseDisk('<?=$name?>')"<?=$erasable?'':' disabled'?>>
|
||||
<input type="button" id="eraseButton" value="_(Erase Pool)_" onclick="eraseDisk()"<?=$erasable?'':' disabled'?>>
|
||||
<?if (_var($var,'fsState')=="Stopped"): $removeable=true; endif;?>
|
||||
<input type="button" id="removeButton" value="_(Remove Pool)_" onclick="removePool('<?=$name?>')"<?=$removeable?'':' disabled'?>>
|
||||
<input type="button" id="removeButton" value="_(Remove Pool)_" onclick="removePool()"<?=$removeable?'':' disabled'?>>
|
||||
<?endif;?>
|
||||
</form>
|
||||
|
||||
@@ -1143,7 +1144,7 @@ _(zfs pool status)_:
|
||||
|
||||
: <input type="submit" id="zfs-button" value="<?=$zfs_cmd=='start' ? _('Scrub') : _('Clear')?>">
|
||||
<?if (! is_upgraded_ZFS_pool($name)):?>
|
||||
<input type="button" id="upgradeButton" value="_(Upgrade Pool)_" onclick="upgradeZpool('<?=$name?>')">
|
||||
<input type="button" id="upgradeButton" value="_(Upgrade Pool)_" onclick="upgradeZpool()">
|
||||
<?endif;?>
|
||||
|
||||
:info_zfs_scrub_help:
|
||||
@@ -1458,7 +1459,7 @@ _(SMART attribute notifications)_:
|
||||
<input type="hidden" name="changeSlots" value="apply">
|
||||
<p>_(Caution)_: _(Renaming the pool will change the share storage allocations)_. _(After renaming the pool, check that your shares are assigned to the proper primary and secondary storage locations)_.</p>
|
||||
_(Name)_:
|
||||
: <input type="text" name="poolName" maxlength="40" value="<?=$name?>">
|
||||
: <input type="text" name="poolName" maxlength="40" value="<?=htmlspecialchars($name)?>">
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -169,12 +169,12 @@ _(Default file system for Array disks)_:
|
||||
:disk_default_file_system_help:
|
||||
|
||||
_(Shutdown time-out)_ (_(seconds)_):
|
||||
: <input type="text" name="shutdownTimeout" maxlength="10" value="<?=$var['shutdownTimeout']?>" class="narrow" placeholder="90">
|
||||
: <input type="number" name="shutdownTimeout" maxlength="10" value="<?=$var['shutdownTimeout']?>" class="narrow" placeholder="90">
|
||||
|
||||
:disk_shutdown_timeout_help:
|
||||
|
||||
_(Tunable (poll_attributes))_:
|
||||
: <input type="text" name="poll_attributes" maxlength="10" value="<?=$var['poll_attributes']?>" class="narrow" placeholder="<?=$var['poll_attributes_default']?>">
|
||||
: <input type="number" name="poll_attributes" maxlength="10" value="<?=$var['poll_attributes']?>" class="narrow" placeholder="<?=$var['poll_attributes_default']?>">
|
||||
|
||||
:disk_tunable_poll_attributes_help:
|
||||
|
||||
@@ -187,7 +187,7 @@ _(Tunable (enable NCQ))_:
|
||||
:disk_tunable_enable_ncq_help:
|
||||
|
||||
_(Tunable (nr_requests))_:
|
||||
: <input type="text" name="nr_requests" maxlength="10" value="<?=$var['nr_requests']?>" class="narrow" placeholder="<?=_($var['nr_requests_default'])?>">
|
||||
: <input type="text" name="nr_requests" maxlength="10" value="<?=htmlspecialchars($var['nr_requests'])?>" class="narrow" placeholder="<?=_($var['nr_requests_default'])?>">
|
||||
|
||||
:disk_tunable_nr_requests_help:
|
||||
|
||||
@@ -203,17 +203,17 @@ _(Tunable (scheduler))_:
|
||||
:disk_tunable_scheduler_help:
|
||||
|
||||
_(Tunable (md_num_stripes))_:
|
||||
: <input type="text" name="md_num_stripes" maxlength="10" value="<?=$var['md_num_stripes']?>" class="narrow" placeholder="<?=$var['md_num_stripes_default']?>">
|
||||
: <input type="number" name="md_num_stripes" maxlength="10" value="<?=$var['md_num_stripes']?>" class="narrow" placeholder="<?=$var['md_num_stripes_default']?>">
|
||||
|
||||
:disk_tunable_md_num_stripes_help:
|
||||
|
||||
_(Tunable (md_queue_limit))_:
|
||||
: <input type="text" name="md_queue_limit" maxlength="10" value="<?=$var['md_queue_limit']?>" class="narrow" placeholder="<?=$var['md_queue_limit_default']?>">
|
||||
: <input type="number" name="md_queue_limit" maxlength="10" value="<?=$var['md_queue_limit']?>" class="narrow" placeholder="<?=$var['md_queue_limit_default']?>">
|
||||
|
||||
:disk_tunable_md_queue_limit_help:
|
||||
|
||||
_(Tunable (md_sync_limit))_:
|
||||
: <input type="text" name="md_sync_limit" maxlength="10" value="<?=$var['md_sync_limit']?>" class="narrow" placeholder="<?=$var['md_sync_limit_default']?>">
|
||||
: <input type="number" name="md_sync_limit" maxlength="10" value="<?=$var['md_sync_limit']?>" class="narrow" placeholder="<?=$var['md_sync_limit_default']?>">
|
||||
|
||||
:disk_tunable_md_sync_limit_help:
|
||||
|
||||
@@ -376,7 +376,7 @@ _(Default SMART controller type)_:
|
||||
:disk_default_smart_controller_help:
|
||||
|
||||
_(Default SMART attribute notifications)_:
|
||||
: <input type="text" name="smCustom" value="<?=_var($var,'smCustom')?>" class="narrow">_(Custom attributes (use comma to separate numbers))_
|
||||
: <input type="text" name="smCustom" value="<?=htmlspecialchars(_var($var,'smCustom'))?>" class="narrow">_(Custom attributes (use comma to separate numbers))_
|
||||
|
||||
<?for ($x = 0; $x < count($preselect); $x++):?>
|
||||
|
||||
|
||||
@@ -15,6 +15,13 @@ Tag="linux"
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
|
||||
<?
|
||||
/* Get the current nfs server version and threads count. */
|
||||
$rpc_nfsd_vers = trim(exec( "plugins/dynamix/scripts/nfsSettings nfs_version" ));
|
||||
$rpc_nfsd_count = trim(exec( "plugins/dynamix/scripts/nfsSettings nfs_count" ))
|
||||
?>
|
||||
|
||||
<script>
|
||||
function checkNFSenable() {
|
||||
var form = document.nfs_enable;
|
||||
@@ -24,6 +31,7 @@ $(checkNFSenable);
|
||||
</script>
|
||||
|
||||
<form markdown="1" name="nfs_enable" method="POST" action="/update.htm" target="progressFrame">
|
||||
|
||||
_(Enable NFS)_:
|
||||
: <select name="shareNFSEnabled" onchange="checkNFSenable()">
|
||||
<?=mk_option($var['shareNFSEnabled'], "no", _('No'));?>
|
||||
@@ -33,10 +41,61 @@ _(Enable NFS)_:
|
||||
:nfs_enable_help:
|
||||
|
||||
_(Tunable (fuse_remember))_:
|
||||
: <input type="text" name="fuse_remember" maxlength="10" value="<?=$var['fuse_remember']?>" class="narrow"><?=_($var['fuse_remember_status'])?>
|
||||
: <input type="number" name="fuse_remember" maxlength="10" value="<?=$var['fuse_remember']?>" class="narrow"><?=_($var['fuse_remember_status'])?>
|
||||
|
||||
:nfs_tunable_fuse_remember_help:
|
||||
|
||||
|
||||
: <input type="submit" name="changeShare" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
</form>
|
||||
|
||||
<form markdown="1" name="nfs_settings" method="POST" action="/update.php" target="progressFrame">
|
||||
<input type="hidden" name="#command" value="/plugins/dynamix/scripts/nfsSettings">
|
||||
<input type="hidden" name="#arg[1]" value="apply">
|
||||
<input type="hidden" id="hidden_rpc_nfsd_vers" name="#arg[2]" value="<?=$rpc_nfsd_vers;?>">
|
||||
<input type="hidden" id="hidden_rpc_nfsd_count" name="#arg[3]" value="<?=$rpc_nfsd_count;?>">
|
||||
|
||||
_(Max Server Protocol Version)_:
|
||||
: <select id="nfs_version" size="1">
|
||||
<?=mk_option($rpc_nfsd_vers, "", "_(NFSv4)_");?>
|
||||
<?=mk_option($rpc_nfsd_vers, "-N 4", "_(NFSv3)_");?>
|
||||
</select>
|
||||
|
||||
:nfs_server_max_protocol_help:
|
||||
|
||||
_(Number of Threads)_:
|
||||
: <select id="nfs_threads" size="1">
|
||||
<?=mk_option($rpc_nfsd_count, "8", "8");?>
|
||||
<?=mk_option($rpc_nfsd_count, "16", "16");?>
|
||||
<?=mk_option($rpc_nfsd_count, "32", "32");?>
|
||||
<?=mk_option($rpc_nfsd_count, "64", "64");?>
|
||||
<?=mk_option($rpc_nfsd_count, "128", "128");?>
|
||||
</select>
|
||||
|
||||
:nfs_threads_help:
|
||||
|
||||
|
||||
: <input type="submit" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
/* Get references to the dropdowns and hidden inputs. */
|
||||
const nfsServerVersion = document.getElementById('nfs_version');
|
||||
const nfsThreads = document.getElementById('nfs_threads');
|
||||
const hiddenRpcNfsdVers = document.getElementById('hidden_rpc_nfsd_vers');
|
||||
const hiddenRpcNfsdCount = document.getElementById('hidden_rpc_nfsd_count');
|
||||
|
||||
/* Check if elements exist. */
|
||||
if (nfsServerVersion && nfsThreads && hiddenRpcNfsdVers && hiddenRpcNfsdCount) {
|
||||
/* Update hidden inputs when the dropdowns change. */
|
||||
nfsServerVersion.addEventListener('change', function () {
|
||||
hiddenRpcNfsdVers.value = this.value;
|
||||
});
|
||||
|
||||
nfsThreads.addEventListener('change', function () {
|
||||
hiddenRpcNfsdCount.value = this.value;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -93,12 +93,12 @@ _(Current listening interfaces)_:
|
||||
<hr>
|
||||
|
||||
_(Include listening interfaces)_:
|
||||
: <textarea name="include" spellcheck="false" cols="80" rows="<?=substr_count($include_interfaces,"\n")+1?>" maxlength="2048" name="text" style="resize:none;width:200px"><?=$include_interfaces?></textarea>
|
||||
: <textarea name="include" spellcheck="false" cols="80" rows="<?=substr_count($include_interfaces,"\n")+1?>" maxlength="2048" name="text" style="resize:none;width:200px"><?=htmlspecialchars($include_interfaces)?></textarea>
|
||||
|
||||
:eth_network_extra_include_help:
|
||||
|
||||
_(Exclude listening interfaces)_:
|
||||
: <textarea name="exclude" spellcheck="false" cols="80" rows="<?=substr_count($exclude_interfaces,"\n")+1?>" maxlength="2048" name="text" style="resize:none;width:200px"><?=$exclude_interfaces?></textarea>
|
||||
: <textarea name="exclude" spellcheck="false" cols="80" rows="<?=substr_count($exclude_interfaces,"\n")+1?>" maxlength="2048" name="text" style="resize:none;width:200px"><?=htmlspecialchars($exclude_interfaces)?></textarea>
|
||||
|
||||
:eth_network_extra_exclude_help:
|
||||
|
||||
|
||||
@@ -93,45 +93,41 @@ _(Rule)_:
|
||||
$(function() {
|
||||
/* Initialize dropdown for NFS and check for hostList cookie. */
|
||||
initDropdownNFS(false);
|
||||
|
||||
if ($.cookie('hostList') != null) {
|
||||
var host = $('input[name="shareHostListNFS"]');
|
||||
host.val($.cookie('hostList'));
|
||||
setTimeout(function() {
|
||||
host.trigger('change');
|
||||
}, 100);
|
||||
var host = $('textarea[name="shareHostListNFS"]');
|
||||
if (host.length) {
|
||||
host.val($.cookie('hostList'));
|
||||
setTimeout(function() {
|
||||
host.trigger('change');
|
||||
}, 100);
|
||||
}
|
||||
$.removeCookie('hostList');
|
||||
}
|
||||
|
||||
<?if ($tabbed):?>
|
||||
/* Conditionally bind click event to tabs if tabbed interface is used. */
|
||||
<?$path=='Shares/Share' ? $t=2 : $t=1;?>
|
||||
$('#tab<?=$t?>').bind({click:function() {
|
||||
initDropdownNFS(true);
|
||||
}});
|
||||
<?endif;?>
|
||||
});
|
||||
|
||||
/* Add an event listener to update the text area to make all rules into a single line before being submitted. */
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
/* Add submit listener to nfsHostListForm if it exists */
|
||||
var form = document.getElementById('nfsHostListForm');
|
||||
form.addEventListener('submit', function(event) {
|
||||
var textarea = document.querySelector('textarea[name="shareHostListNFS"]');
|
||||
|
||||
/* Split the content into lines. */
|
||||
var lines = textarea.value.split('\n');
|
||||
|
||||
/* Filter out empty lines or lines that contain only whitespace, and remove carriage returns and excessive spaces within lines. */
|
||||
var cleanedLines = lines.map(function(line) {
|
||||
/* Remove carriage returns and spaces within each line. */
|
||||
return line.replace(/[\r\s]+/g, '');
|
||||
}).filter(function(line) {
|
||||
/* Keep only non-empty lines. */
|
||||
return line.length > 0;
|
||||
if (form) {
|
||||
form.addEventListener('submit', function(event) {
|
||||
var textarea = document.querySelector('textarea[name="shareHostListNFS"]');
|
||||
if (textarea) {
|
||||
var lines = textarea.value.split('\n');
|
||||
var cleanedLines = lines.map(function(line) {
|
||||
return line.replace(/[\r\s]+/g, '');
|
||||
}).filter(function(line) {
|
||||
return line.length > 0;
|
||||
});
|
||||
textarea.value = cleanedLines.join(' ');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Join the remaining lines with a single space. */
|
||||
textarea.value = cleanedLines.join(' ');
|
||||
/* Conditionally bind click event to tabs */
|
||||
<?if ($tabbed):?>
|
||||
$('#tab<?= $path == 'Shares/Share' ? 2 : 1 ?>').on('click', function() {
|
||||
initDropdownNFS(true);
|
||||
});
|
||||
<?endif;?>
|
||||
});
|
||||
|
||||
/* Function to initialize or reset the NFS dropdown */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Menu="Device:2 New:2"
|
||||
Title="Self-Test"
|
||||
Tag="wrench"
|
||||
Cond="strpos(_var($disks[$name],'status'),'_NP')===false"
|
||||
Cond="array_key_exists($name, $disks) || array_key_exists($name, $devs)"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
|
||||
@@ -15,11 +15,15 @@ Tag="share-alt-square"
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
if (!empty($name) && !array_key_exists($name, $shares)) {
|
||||
echo "<script>done()</script>";
|
||||
return;
|
||||
}
|
||||
$width = [123,300];
|
||||
|
||||
if ($name == "") {
|
||||
/* default values when adding new share. */
|
||||
$share = [
|
||||
/* default values when adding new share. */
|
||||
$share = [
|
||||
"nameOrig" => "",
|
||||
"name" => "",
|
||||
"comment" => "",
|
||||
@@ -33,13 +37,9 @@ if ($name == "") {
|
||||
"cachePool2" => "",
|
||||
"cow" => "auto"
|
||||
];
|
||||
} elseif (array_key_exists($name, $shares)) {
|
||||
} else {
|
||||
/* edit existing share. */
|
||||
$share = $shares[$name];
|
||||
} else {
|
||||
/* handle share deleted case. */
|
||||
echo "<p class='notice'>"._('Share')." '".htmlspecialchars($name)."' "._('has been deleted').".</p><input type='button' value=\""._('Done')."\" onclick='done()'>";
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the configuration is pools only, then no array disks are available. */
|
||||
@@ -56,23 +56,26 @@ if ((! $share['cachePool']) && ($share['cachePool2'])) {
|
||||
$share['cachePool2'] = "";
|
||||
}
|
||||
|
||||
/* Correct a situation in previous Unraid versions where an array only share has a useCache defined. */
|
||||
if ((!$poolsOnly) && ($share['useCache'] == "no")) {
|
||||
$share['cachePool'] = "";
|
||||
}
|
||||
|
||||
/* Check for non existent pool device. */
|
||||
if (($share['cachePool'] && !in_array($share['cachePool'], $pools)) || ($poolsOnly && !$share['cachePool'])) {
|
||||
$poolDefined = false;
|
||||
if (($share['cachePool'] && !in_array($share['cachePool'], $pools))) {
|
||||
$share['useCache'] = $share['cachePool2'] ? "yes" : ($poolsOnly ? "no" : "yes");
|
||||
$poolDefined = false;
|
||||
} else {
|
||||
$share['useCache'] = $share['useCache'] ?: ($poolsOnly ? "only" : "no");
|
||||
$poolDefined = true;
|
||||
}
|
||||
|
||||
/* Check for pool 2 (or array) being defined. */
|
||||
$poolDefined2 = true;
|
||||
if ((($share['useCache'] == "yes") || ($share['useCache'] == "prefer")) && ($poolsOnly) && (!$share['cachePool2'])) {
|
||||
$poolDefined2 = true;
|
||||
$share['useCache'] = "only";
|
||||
} else if ($share['cachePool2']) {
|
||||
$poolDefined2 = in_array($share['cachePool2'], $pools);
|
||||
} else {
|
||||
$poolDefined2 = true;
|
||||
}
|
||||
|
||||
$cachePoolCapitalized = compress(my_disk($share['cachePool'],$display['raw']));
|
||||
@@ -551,6 +554,9 @@ _(Mover action)_:
|
||||
<script>
|
||||
let form = document.share_edit;
|
||||
|
||||
/* Global flag to skip prepareEdit. */
|
||||
let skipPrepareEdit = false;
|
||||
|
||||
/* Primary variables to check for valid selection of missing pool. */
|
||||
let changeMadePrimary = false;
|
||||
let checkRequiredPrimary = false;
|
||||
@@ -569,6 +575,7 @@ function initDropdown(forceInit) {
|
||||
destroyDropdownIfExists('#s5');
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
initializeDropdown('#s1', "_(All)_", <?=$width[1]?>);
|
||||
initializeDropdown('#s2', "_(None)_", <?=$width[1]?>);
|
||||
initializeDropdown('#s3', "_(All)_", <?=$width[1]?>);
|
||||
@@ -580,26 +587,42 @@ function initDropdown(forceInit) {
|
||||
|
||||
function initializeDropdown(selector, emptyText, width, firstItemChecksAll = false) {
|
||||
try {
|
||||
$(selector).dropdownchecklist({
|
||||
emptyText: emptyText,
|
||||
width: width,
|
||||
explicitClose: "..._(close)_",
|
||||
firstItemChecksAll: firstItemChecksAll
|
||||
});
|
||||
if ($(selector).length) {
|
||||
$(selector).dropdownchecklist({
|
||||
emptyText: emptyText,
|
||||
width: width,
|
||||
explicitClose: "..._(close)_",
|
||||
firstItemChecksAll: firstItemChecksAll
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error initializing ${selector}: ` + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function destroyDropdownIfExists(selector) {
|
||||
try {
|
||||
$(selector).dropdownchecklist('destroy');
|
||||
} catch (e) {
|
||||
if (e.message.includes('prior to initialization')) {
|
||||
console.log(`${selector} not initialized, skipping destroy.`);
|
||||
} else {
|
||||
console.error(`Error destroying ${selector}: ` + e.message);
|
||||
if ($(selector).length) {
|
||||
$(selector).dropdownchecklist('destroy');
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
function enableDropdownIfExists(selector) {
|
||||
try {
|
||||
if ($(selector).length) {
|
||||
$(selector).dropdownchecklist('enable');
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
function disableDropdownIfExists(selector) {
|
||||
try {
|
||||
if ($(selector).length) {
|
||||
$(selector).dropdownchecklist('disable');
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -786,22 +809,6 @@ function updateCOW(pool, slow) {
|
||||
}
|
||||
}
|
||||
|
||||
function enableDropdownIfExists(selector) {
|
||||
try {
|
||||
$(selector).dropdownchecklist('enable');
|
||||
} catch (e) {
|
||||
console.log(`${selector} not initialized, cannot enable.`);
|
||||
}
|
||||
}
|
||||
|
||||
function disableDropdownIfExists(selector) {
|
||||
try {
|
||||
$(selector).dropdownchecklist('disable');
|
||||
} catch (e) {
|
||||
console.log(`${selector} not initialized, cannot disable.`);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unite selected options into a comma-separated string */
|
||||
function unite(field) {
|
||||
const list = [];
|
||||
@@ -915,6 +922,15 @@ function parseDiskSize(sizeStr) {
|
||||
|
||||
/* Compose input fields. */
|
||||
function prepareEdit() {
|
||||
/* Skip the function if readShare() filled the values */
|
||||
if (skipPrepareEdit) {
|
||||
/* Reset the flag. */
|
||||
skipPrepareEdit = false;
|
||||
|
||||
/* Allow the form to submit. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Declare variables at the function scope */
|
||||
let share, reserved, pools;
|
||||
|
||||
@@ -1015,38 +1031,39 @@ function prepareEdit() {
|
||||
}
|
||||
|
||||
function readShare() {
|
||||
/* Declare variables at the function scope */
|
||||
var name, data, disk, include, exclude, i, j;
|
||||
let name, data;
|
||||
|
||||
name = $('select[name="readshare"]').val();
|
||||
initDropdown(true);
|
||||
name = $('select[name="readshare"]').val();
|
||||
|
||||
$.get('/webGui/include/ShareData.php', { name: name }, function(json) {
|
||||
data = $.parseJSON(json);
|
||||
form.shareAllocator.value = data.allocator;
|
||||
form.shareFloor.value = data.floor;
|
||||
form.shareSplitLevel.value = data.splitLevel;
|
||||
form.shareInclude.value = data.include;
|
||||
form.shareExclude.value = data.exclude;
|
||||
form.shareUseCache.value = data.useCache;
|
||||
form.shareCOW.value = data.cow;
|
||||
$.get('/webGui/include/ShareData.php', { name: name }, function(json) {
|
||||
data = $.parseJSON(json);
|
||||
let form = document.forms['share_edit'];
|
||||
|
||||
for (i = 0; (disk = data.include.split(',')[i]); i++) {
|
||||
for (j = 0; (include = form.shareInclude.options[j]); j++) {
|
||||
if (include.value == disk) include.selected = true;
|
||||
}
|
||||
/* Fill in the form values */
|
||||
form.shareAllocator.value = data.allocator;
|
||||
form.shareFloor.value = data.floor;
|
||||
form.shareSplitLevel.value = data.splitLevel;
|
||||
form.shareInclude.value = data.include;
|
||||
form.shareExclude.value = data.exclude;
|
||||
form.shareUseCache.value = data.useCache;
|
||||
form.shareCachePool2.value = data.cachePool2;
|
||||
form.shareCOW.value = data.cow;
|
||||
|
||||
/* Populate the primary storage field (shareCachePool) */
|
||||
let primaryField = document.getElementById('primary');
|
||||
if (primaryField) {
|
||||
/* Set to retrieved value or default. */
|
||||
primaryField.value = data.cachePool || '';
|
||||
}
|
||||
|
||||
for (i = 0; (disk = data.exclude.split(',')[i]); i++) {
|
||||
for (j = 0; (exclude = form.shareExclude.options[j]); j++) {
|
||||
if (exclude.value == disk) exclude.selected = true;
|
||||
}
|
||||
}
|
||||
/* Set flag to skip prepareEdit */
|
||||
skipPrepareEdit = true;
|
||||
|
||||
initDropdown(false);
|
||||
});
|
||||
|
||||
$(form).find('select').trigger('change');
|
||||
/* Enable and trigger the submit button */
|
||||
const submitButton = document.getElementById('cmdEditShare');
|
||||
submitButton.disabled = false;
|
||||
submitButton.click();
|
||||
});
|
||||
}
|
||||
|
||||
function writeShare(data, n, i) {
|
||||
@@ -1078,12 +1095,14 @@ function writeShare(data, n, i) {
|
||||
newData[i]['shareInclude'] = '<?=addslashes(htmlspecialchars($share['include']))?>';
|
||||
newData[i]['shareExclude'] = '<?=addslashes(htmlspecialchars($share['exclude']))?>';
|
||||
newData[i]['shareUseCache'] = '<?=addslashes(htmlspecialchars($share['useCache']))?>';
|
||||
newData[i]['shareCachePool'] = '<?=addslashes(htmlspecialchars($share['cachePool']))?>';
|
||||
newData[i]['shareCachePool2'] = '<?=addslashes(htmlspecialchars($share['cachePool2']))?>';
|
||||
newData[i]['cmdEditShare'] = 'Apply';
|
||||
i++;
|
||||
}
|
||||
});
|
||||
toggleButton('writeshare', true);
|
||||
$('div.spinner.fixed').show(slow);
|
||||
$('div.spinner.fixed').show('slow');
|
||||
writeShare(newData, 0, i);
|
||||
}
|
||||
}
|
||||
@@ -1325,7 +1344,7 @@ $(function() {
|
||||
<?endif;?>
|
||||
initDropdown(true);
|
||||
<?if ($tabbed):?>
|
||||
$('#tab1').bind({
|
||||
$('#tab1').on({
|
||||
click: function() {
|
||||
initDropdown(true);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ Tag="share-alt"
|
||||
$disabled = _var($var,'fsState')!='Stopped' ? 'disabled' : '';
|
||||
$disks = array_filter($disks,'my_disks');
|
||||
$width = [166,300];
|
||||
|
||||
/* Fetch the file-max value from the system. */
|
||||
$fileMax = (int) file_get_contents('/proc/sys/fs/file-max');
|
||||
?>
|
||||
<script>
|
||||
$(function() {
|
||||
@@ -27,8 +30,12 @@ $(function() {
|
||||
$('#s2').dropdownchecklist({emptyText:"_(None)_", width:<?=$width[0]?>, explicitClose:"..._(close)_"});
|
||||
presetShare(document.share_settings);
|
||||
});
|
||||
|
||||
/* Maximum file count allowed. */
|
||||
const fileMax = <?=json_encode($fileMax);?>;
|
||||
|
||||
// Simulate the original input field
|
||||
function prepareShare(form) {
|
||||
async function prepareShare(form) {
|
||||
var include = '';
|
||||
for (var i=0,item; item=form.shareUserInclude.options[i]; i++) {
|
||||
if (item.selected) {
|
||||
@@ -51,7 +58,30 @@ function prepareShare(form) {
|
||||
item = form.shareUserExclude.options[0];
|
||||
item.value = exclude;
|
||||
item.selected = true;
|
||||
|
||||
/* Validate file count input against fileMax */
|
||||
try {
|
||||
const fileCountInput = form.querySelector('#file_count');
|
||||
if (!fileCountInput) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fileCountValue = parseInt(fileCountInput.value, 10);
|
||||
if (isNaN(fileCountValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileCountValue > fileMax) {
|
||||
fileCountInput.value = fileMax;
|
||||
}
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Allow form submission */
|
||||
return true;
|
||||
}
|
||||
|
||||
function presetShare(form,shares) {
|
||||
var disabled = shares==null ? <?=$disabled ? 'true':'false'?> : shares=='-';
|
||||
var onOff = disabled ? 'disable':'enable';
|
||||
@@ -61,7 +91,7 @@ function presetShare(form,shares) {
|
||||
$('#s2').dropdownchecklist(onOff);
|
||||
}
|
||||
</script>
|
||||
<form markdown="1" name="share_settings" method="POST" action="/update.htm" target="progressFrame" onsubmit="prepareShare(this)">
|
||||
<form markdown="1" name="share_settings" method="POST" action="/update.htm" target="progressFrame" onsubmit="return prepareShare(this)">
|
||||
|
||||
_(Enable disk shares)_:
|
||||
: <select name="shareDisk" <?=$disabled?>>
|
||||
@@ -123,6 +153,11 @@ _(Tunable (enable Direct IO))_:
|
||||
|
||||
:shares_tunable_direct_io_help:
|
||||
|
||||
_(Number of fuse File Descriptors)_:
|
||||
: <input type="text" id="file_count" name="shareNOFILE" maxlength="10" value="<?=htmlspecialchars($var['shareNOFILE']);?>" class="narrow" placeholder="40960" <?=$disabled?>><span id="file_max_display">Maximum: <?=$fileMax;?></span>
|
||||
|
||||
:shares_fuse_file_descriptors_io_help:
|
||||
|
||||
|
||||
: <input type="submit" name="changeShare" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()"><?if ($disabled):?>*_(Array must be **Stopped** to change)_*<?endif;?>
|
||||
</form>
|
||||
|
||||
@@ -34,7 +34,7 @@ function applyCfg() {
|
||||
if (string === "BIND=") {
|
||||
string = "";
|
||||
}
|
||||
$.get( "/plugins/dynamix/include/update.vfio-pci-cfg.php", { cfg: string } )
|
||||
$.post( "/plugins/dynamix/include/update.vfio-pci-cfg.php", { cfg: string } )
|
||||
.done(function(d) {
|
||||
if (d==1) {
|
||||
addRebootNotice(message);
|
||||
|
||||
@@ -194,15 +194,15 @@ _(Syslinux configuration)_:
|
||||
$label = ($i) ? array_shift($area):$title;
|
||||
$start = in_array($menu,$area);
|
||||
if ($start) unset($area[array_search($menu,$area)]);
|
||||
?><span id="label-<?=$i?>" class="<?=$start?'array':'system'?>"><?=$label?>
|
||||
?><span id="label-<?=$i?>" class="<?=$start?'array':'system'?>"><?=htmlspecialchars($label)?>
|
||||
<?if ($i):?><span style="float:right"><input type="radio" id="input-<?=$i?>" class="menu" <?=$start?'checked':''?> title="_(Set default boot menu)_" onchange="changeMenu(this.form,this.id,true)"></span><?endif;?></span>
|
||||
<textarea class="menu" id="menu-<?=$i++?>" spellcheck="false" cols="80" rows="<?=count($area)?>" maxlength="2048"><?=implode("\n",$area)?></textarea>
|
||||
<textarea class="menu" id="menu-<?=$i++?>" spellcheck="false" cols="80" rows="<?=count($area)?>" maxlength="2048"><?=htmlspecialchars(implode("\n",$area))?></textarea>
|
||||
<?endforeach;?>
|
||||
|
||||
</div>
|
||||
<div markdown="1" class="advanced">
|
||||
_(Syslinux configuration)_:
|
||||
: <textarea class="raw" name="raw" spellcheck="false" cols="80" rows="<?=substr_count($current,"\n")+1?>" maxlength="2048"><?=$current?></textarea>
|
||||
: <textarea class="raw" name="raw" spellcheck="false" cols="80" rows="<?=substr_count($current,"\n")+1?>" maxlength="2048"><?=htmlspecialchars($current)?></textarea>
|
||||
|
||||
</div>
|
||||
_(Server boot mode)_:
|
||||
|
||||
@@ -95,7 +95,7 @@ _(Local syslog server)_:
|
||||
<?=mk_option(_var($syslog,'server_protocol'), "tcp", _("TCP"))?>
|
||||
<?=mk_option(_var($syslog,'server_protocol'), "both", _("Both"))?>
|
||||
</select>
|
||||
<input type="text" name="server_port" class="trim" value="<?=_var($syslog,'server_port')?>" maxlength="5" placeholder="514">
|
||||
<input type="number" name="server_port" class="trim" value="<?=_var($syslog,'server_port')?>" maxlength="5" placeholder="514" pattern="([0-9]{1,5})">
|
||||
|
||||
:syslog_local_server_help:
|
||||
|
||||
@@ -155,7 +155,7 @@ _(Local syslog number of files)_:
|
||||
</div>
|
||||
|
||||
_(Remote syslog server)_:
|
||||
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=_var($syslog,'remote_server')?>" maxlength="50" placeholder="_(name or ip address)_"></span>
|
||||
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=htmlspecialchars(_var($syslog,'remote_server'))?>" maxlength="50" placeholder="_(name or ip address)_"></span>
|
||||
<select name="remote_protocol" class="narrow">
|
||||
<?=mk_option(_var($syslog,'remote_protocol'), "udp", _("UDP"))?>
|
||||
<?=mk_option(_var($syslog,'remote_protocol'), "tcp", _("TCP"))?>
|
||||
|
||||
@@ -14,12 +14,11 @@ Tag="user"
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?if (!array_key_exists($name, $users)):?>
|
||||
<p class="notice"><?=sprintf(_('User %s has been deleted'),htmlspecialchars($name))?>.</p><br>
|
||||
<input type="button" value="_(Done)_" onClick="done()">
|
||||
<?return;?>
|
||||
<?endif;?>
|
||||
<?
|
||||
if (!array_key_exists($name, $users)) {
|
||||
echo "<script>done()</script>";
|
||||
return;
|
||||
}
|
||||
$user = "/boot/config/plugins/dynamix/users/$name.png";
|
||||
$void = "<img src='/webGui/images/user.png' width='48' height='48' id='image' onclick='$("#drop").click()' style='cursor:pointer' title='"._('Click to select PNG file')."'>";
|
||||
$icon = "<i class='fa fa-trash top' title='"._('Restore default image')."' onclick='restore()'></i>";
|
||||
|
||||
@@ -15,19 +15,17 @@ Tag="users"
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$submenu = !empty($display['users']) && substr($display['users'],0,5)!='Tasks';
|
||||
if ($submenu) $path = './Users';
|
||||
ksort($users);
|
||||
?>
|
||||
<div id="title" class="title"><span class="left"><i class="fa fa-bell title"></i>_(Management Access)_</span></div>
|
||||
<?$img = "/boot/config/plugins/dynamix/users/root.png"?>
|
||||
<div class="user-list" style="text-align:center"><a class="<?=(!empty($users['root']['desc']) ? 'info' : '')?>" href="<?=$path?>/UserEdit?name=root"><img src="<?=(file_exists($img) ? autov($img) : '/webGui/images/user.png')?>" class="picture" border="0" width="48" height="48"><br>root<span><?=htmlspecialchars($users['root']['desc'])?></span></a></div>
|
||||
<div class="user-list" style="text-align:center"><a class="<?=(!empty($users['root']['desc']) ? 'info' : '')?>" href="/<?=$path?>/UserEdit?name=root"><img src="<?=(file_exists($img) ? autov($img) : '/webGui/images/user.png')?>" class="picture" border="0" width="48" height="48"><br>root<span><?=htmlspecialchars($users['root']['desc'])?></span></a></div>
|
||||
|
||||
<div class="title"><span class="left"><i class="fa fa-cloud title"></i>_(Shares Access)_</span></div>
|
||||
<?foreach ($users as $user):?>
|
||||
<?if ($user['name'] == 'root') continue;?>
|
||||
<?$img = "/boot/config/plugins/dynamix/users/{$user['name']}.png"?>
|
||||
<div class="user-list" style="text-align:center"><a class="<?=(!empty($user['desc']) ? 'info' : '')?>" href="<?=$path?>/UserEdit?name=<?=htmlspecialchars(urlencode($user['name']))?>"><img src="<?=(file_exists($img) ? autov($img) : '/webGui/images/user.png')?>" class="picture" border="0" width="48" height="48"><br><?=htmlspecialchars($user['name'])?><span><?=htmlspecialchars($user['desc'])?></span></a></div>
|
||||
<div class="user-list" style="text-align:center"><a class="<?=(!empty($user['desc']) ? 'info' : '')?>" href="/<?=$path?>/UserEdit?name=<?=htmlspecialchars(urlencode($user['name']))?>"><img src="<?=(file_exists($img) ? autov($img) : '/webGui/images/user.png')?>" class="picture" border="0" width="48" height="48"><br><?=htmlspecialchars($user['name'])?><span><?=htmlspecialchars($user['desc'])?></span></a></div>
|
||||
<?endforeach;?>
|
||||
|
||||
<?if (count($users)==1):?>
|
||||
@@ -35,6 +33,6 @@ _(No users are defined)_. _(Click **Add User** to create a user for remote share
|
||||
<?endif;?>
|
||||
|
||||
<div style='clear:both'></div>
|
||||
<form method="POST" action="<?=$path?>/UserAdd">
|
||||
<input type="submit" value="_(Add User)_"><?if ($submenu):?><input type="button" value="_(Done)_" onclick="done()"><?endif;?>
|
||||
<form method="POST" action="/<?=$path?>/UserAdd">
|
||||
<input type="submit" value="_(Add User)_"><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
|
||||
@@ -480,10 +480,10 @@ $theme_dark = in_array($display['theme'], ['black', 'gray']);
|
||||
</div>
|
||||
<div class="content">
|
||||
<h1>
|
||||
<?=$var['NAME']?>
|
||||
<?=htmlspecialchars($var['NAME'])?>
|
||||
</h1>
|
||||
<h2>
|
||||
<?=$var['COMMENT']?>
|
||||
<?=htmlspecialchars($var['COMMENT'])?>
|
||||
</h2>
|
||||
|
||||
<div class="case">
|
||||
|
||||
@@ -306,8 +306,8 @@ $THEME_DARK = in_array($display['theme'],['black','gray']);
|
||||
</div>
|
||||
<div class="content">
|
||||
<header>
|
||||
<h1><?=$var['NAME']?></h1>
|
||||
<h2><?=$var['COMMENT']?></h2>
|
||||
<h1><?=htmlspecialchars($var['NAME'])?></h1>
|
||||
<h2><?=htmlspecialchars($var['COMMENT'])?></h2>
|
||||
<p><?=_('Please set a password for the root user account')?>.</p>
|
||||
<p><?=_('Max password length is 128 characters')?>.</p>
|
||||
</header>
|
||||
|
||||
@@ -126,7 +126,7 @@ if ($_POST['vms']) {
|
||||
if (!isset($domain_cfg["CONSOLE"])) $vmrcconsole = "web" ; else $vmrcconsole = $domain_cfg["CONSOLE"] ;
|
||||
if (!isset($domain_cfg["RDPOPT"])) $vmrcconsole .= ";no" ; else $vmrcconsole .= ";".$domain_cfg["RDPOPT"] ;
|
||||
$WebUI = html_entity_decode($arrConfig["template"]["webui"]);
|
||||
$menu = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", htmlentities($log,ENT_QUOTES), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), htmlentities($log,ENT_QUOTES),addslashes($fstype), $vmrcconsole,false,addslashes(str_replace('"',"'",$WebUI)));
|
||||
$menu = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", htmlentities($vm,ENT_QUOTES), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), htmlentities($log,ENT_QUOTES),addslashes($fstype), $vmrcconsole,false,addslashes(str_replace('"',"'",$WebUI)));
|
||||
$icon = $lv->domain_get_icon_url($res);
|
||||
switch ($state) {
|
||||
case 'running':
|
||||
|
||||
@@ -720,7 +720,7 @@ if (isset($myPage['Load']) && $myPage['Load']>0) echo "\n<script>timers.reload =
|
||||
echo "<div class='tabs'>";
|
||||
$tab = 1;
|
||||
$pages = [];
|
||||
if (!empty($myPage['text'])) $pages[$myPage['name']] = $myPage;
|
||||
if (!empty($myPage['text']) && page_enabled($myPage)) $pages[$myPage['name']] = $myPage;
|
||||
if (_var($myPage,'Type')=='xmenu') $pages = array_merge($pages, find_pages($myPage['name']));
|
||||
if (isset($myPage['Tabs'])) $display['tabs'] = strtolower($myPage['Tabs'])=='true' ? 0 : 1;
|
||||
$tabbed = $display['tabs']==0 && count($pages)>1;
|
||||
@@ -728,7 +728,7 @@ $tabbed = $display['tabs']==0 && count($pages)>1;
|
||||
foreach ($pages as $page) {
|
||||
$close = false;
|
||||
if (isset($page['Title'])) {
|
||||
eval("\$title=\"".htmlspecialchars($page['Title'])."\";");
|
||||
eval("\$title=\"{$page['Title']}\";");
|
||||
if ($tabbed) {
|
||||
echo "<div class='tab'><input type='radio' id='tab{$tab}' name='tabs' onclick='settab(this.id)'><label for='tab{$tab}'>";
|
||||
echo tab_title($title,$page['root'],_var($page,'Tag',false));
|
||||
@@ -745,7 +745,7 @@ foreach ($pages as $page) {
|
||||
if (isset($page['Type']) && $page['Type']=='menu') {
|
||||
$pgs = find_pages($page['name']);
|
||||
foreach ($pgs as $pg) {
|
||||
@eval("\$title=\"".htmlspecialchars($pg['Title'])."\";");
|
||||
@eval("\$title=\"{$pg['Title']}\";");
|
||||
$icon = _var($pg,'Icon',"<i class='icon-app PanelIcon'></i>");
|
||||
if (substr($icon,-4)=='.png') {
|
||||
$root = $pg['root'];
|
||||
|
||||
@@ -117,7 +117,7 @@ foreach ($disks as $name => $disk) {
|
||||
} else $luks = "";
|
||||
echo "<tr><td><a class='view' href=\"/$path/Browse?dir=/mnt/$name\"><i class=\"icon-u-tab\" title=\"",_('Browse')," /mnt/$name\"></i></a>";
|
||||
echo "<a class='info nohand' onclick='return false'><i class='fa fa-$orb orb $color-orb'></i><span style='left:18px'>$help</span></a>$luks<a href=\"/$path/Disk?name=$name\" onclick=\"$.cookie('one','tab1')\">$name</a></td>";
|
||||
echo "<td>"._var($disk,'comment')."</td>";
|
||||
echo "<td>",htmlspecialchars(_var($disk,'comment')),"</td>";
|
||||
echo "<td>",disk_share_settings(_var($var,'shareSMBEnabled'), $sec[$name]),"</td>";
|
||||
echo "<td>",disk_share_settings(_var($var,'shareNFSEnabled'), $sec_nfs[$name]),"</td>";
|
||||
$cmd="/webGui/scripts/disk_size&arg1=$name&arg2=ssz2";
|
||||
|
||||
@@ -50,7 +50,7 @@ $match = $_POST['match'];
|
||||
$checkbox = $_POST['multiSelect']=='true' ? "<input type='checkbox'>" : "";
|
||||
|
||||
/* Excluded folders to not show in the dropdown in the '/mnt/' directory only. */
|
||||
$excludedFolders = ["RecycleBin", "addons", "remotes", "rootshare", "user0"];
|
||||
$excludedFolders = ["RecycleBin", "addons", "rootshare", "user0"];
|
||||
|
||||
echo "<ul class='jqueryFileTree'>";
|
||||
if ($_POST['show_parent']=='true' && is_top($rootdir)) echo "<li class='directory collapsed'>$checkbox<a href='#' rel=\"".htmlspecialchars(dirname($rootdir))."\">..</a></li>";
|
||||
|
||||
@@ -288,13 +288,6 @@ function transpose_user_path($path) {
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
// custom parse_ini_file/string functions to deal with '#' comment lines
|
||||
function my_parse_ini_string($text, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
||||
return parse_ini_string(preg_replace('/^#/m',';',$text),$sections,$scanner);
|
||||
}
|
||||
function my_parse_ini_file($file, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
||||
return my_parse_ini_string(file_get_contents($file),$sections,$scanner);
|
||||
}
|
||||
function cpu_list() {
|
||||
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
|
||||
return $cpus;
|
||||
@@ -417,4 +410,10 @@ function write_logging($value) {
|
||||
if (!$debug) return;
|
||||
file_put_contents('/tmp/my_mkdir_output', $value, FILE_APPEND);
|
||||
}
|
||||
|
||||
function device_exists($name)
|
||||
{
|
||||
global $disks,$devs;
|
||||
return (array_key_exists($name, $disks) && !str_contains(_var($disks[$name],'status'),'_NP')) || (array_key_exists($name, $devs));
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -42,8 +42,16 @@ function build_pages($pattern) {
|
||||
}
|
||||
}
|
||||
|
||||
function page_enabled(&$page)
|
||||
{
|
||||
global $var,$disks,$devs,$users,$shares,$sec,$sec_nfs,$name,$display,$pool_devices;
|
||||
$enabled = true;
|
||||
if (isset($page['Cond'])) eval("\$enabled={$page['Cond']};");
|
||||
return $enabled;
|
||||
}
|
||||
|
||||
function find_pages($item) {
|
||||
global $docroot,$site,$var,$disks,$devs,$users,$shares,$sec,$sec_nfs,$name,$display,$pool_devices;
|
||||
global $site;
|
||||
$pages = [];
|
||||
foreach ($site as $page) {
|
||||
if (empty($page['Menu'])) continue;
|
||||
@@ -55,9 +63,7 @@ function find_pages($item) {
|
||||
while ($menu !== false) {
|
||||
[$menu,$rank] = my_explode(':',$menu);
|
||||
if ($menu == $item) {
|
||||
$enabled = true;
|
||||
if (isset($page['Cond'])) eval("\$enabled={$page['Cond']};");
|
||||
if ($enabled) $pages["$rank{$page['name']}"] = $page;
|
||||
if (page_enabled($page)) $pages["$rank{$page['name']}"] = $page;
|
||||
break;
|
||||
}
|
||||
$menu = strtok(' ');
|
||||
@@ -69,6 +75,7 @@ function find_pages($item) {
|
||||
|
||||
function tab_title($title,$path,$tag) {
|
||||
global $docroot,$pools;
|
||||
$title=htmlspecialchars(html_entity_decode($title));
|
||||
$names = implode('|',array_merge(['disk','parity'],$pools));
|
||||
if (preg_match("/^($names)/",$title)) {
|
||||
$device = strtok($title,' ');
|
||||
|
||||
@@ -17,7 +17,7 @@ function unscript($text) {
|
||||
}
|
||||
// remove malicious HTML elements
|
||||
function untangle($text) {
|
||||
return preg_replace('#<.+?>(.*?)</.+?>#','',html_entity_decode($text));
|
||||
return strip_tags(html_entity_decode($text));
|
||||
}
|
||||
// remove malicious code appended after string variable
|
||||
function unbundle($text) {
|
||||
|
||||
@@ -187,7 +187,17 @@ define('LUKS_STATUS_UNENCRYPTED', 2);
|
||||
|
||||
// Build table
|
||||
$row = 0;
|
||||
|
||||
/* Get the first pool if needed. */
|
||||
$firstPool = $pools_check[0] ?? "";
|
||||
foreach ($shares as $name => $share) {
|
||||
/* Correct a situation in previous Unraid versions where an array only share has a useCache defined. */
|
||||
if ((!$poolsOnly) && ($share['useCache'] == "no")) {
|
||||
$share['cachePool'] = "";
|
||||
} else if (($poolsOnly) && (!$share['cachePool'])) {
|
||||
$share['cachePool'] = $firstPool;
|
||||
}
|
||||
|
||||
/* Is cachePool2 defined? If it is we need to show the cache pool 2 device name instead of 'Array'. */
|
||||
if ($share['cachePool2']) {
|
||||
$array = compress(my_disk($share['cachePool2'],$display['raw']));
|
||||
@@ -214,8 +224,8 @@ foreach ($shares as $name => $share) {
|
||||
$share_valid = true;
|
||||
}
|
||||
|
||||
/* When there is no array, all pools are treated as 'only' cache. If useCache is "no" with an array, this is invalid and useCache has to be 'only'. */
|
||||
if ((($poolsOnly) && (! $share['cachePool2'])) || ((! $poolsOnly) && ($share['cachePool']) && ($share['useCache'] == "no"))) {
|
||||
/* When there is no array, all pools are treated as 'only' cache. */
|
||||
if (($poolsOnly) && (! $share['cachePool2'])) {
|
||||
$share['useCache'] = 'only';
|
||||
}
|
||||
|
||||
@@ -261,10 +271,10 @@ foreach ($shares as $name => $share) {
|
||||
}
|
||||
}
|
||||
|
||||
echo "<tr><td><a class='view' href=\"/$path/Browse?dir=/mnt/user/", rawurlencode($name), "\"><i class=\"icon-u-tab\" title=\"", _('Browse'), " /mnt/user/" . rawurlencode($name), "\"></i></a>";
|
||||
echo "<tr><td><a class='view' href=\"/$path/Browse?dir=/mnt/user/", htmlspecialchars($name), "\"><i class=\"icon-u-tab\" title=\"", _('Browse'), " /mnt/user/" . htmlspecialchars($name), "\"></i></a>";
|
||||
echo "<a class='info nohand' onclick='return false'><i class='fa fa-$orb orb $color-orb'></i><span style='left:18px'>$help</span></a>$luks<a href=\"/$path/Share?name=";
|
||||
echo rawurlencode($name), "\" onclick=\"$.cookie('one','tab1')\">$name</a></td>";
|
||||
echo "<td>{$share['comment']}</td>";
|
||||
echo "<td>", htmlspecialchars(_var($share,'comment')), "</td>";
|
||||
echo "<td>", user_share_settings($var['shareSMBEnabled'], $sec[$name]), "</td>";
|
||||
echo "<td>", user_share_settings($var['shareNFSEnabled'], $sec_nfs[$name]), "</td>";
|
||||
|
||||
|
||||
@@ -39,12 +39,19 @@ function file_put_contents_atomic($filename,$data) {
|
||||
}
|
||||
return strlen($data);
|
||||
}
|
||||
// custom parse_ini_file/string functions to deal with '#' comment lines and remove html/php tags
|
||||
function my_parse_ini_string($text, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
||||
return parse_ini_string(strip_tags(html_entity_decode(preg_replace('/^#.*$/m','',$text))),$sections,$scanner);
|
||||
}
|
||||
function my_parse_ini_file($file, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
||||
return my_parse_ini_string(file_get_contents($file),$sections,$scanner);
|
||||
}
|
||||
function parse_plugin_cfg($plugin, $sections=false, $scanner=INI_SCANNER_NORMAL) {
|
||||
global $docroot;
|
||||
$ram = "$docroot/plugins/$plugin/default.cfg";
|
||||
$rom = "/boot/config/plugins/$plugin/$plugin.cfg";
|
||||
$cfg = file_exists($ram) ? parse_ini_file($ram, $sections, $scanner) : [];
|
||||
return file_exists($rom) ? array_replace_recursive($cfg, parse_ini_file($rom, $sections, $scanner)) : $cfg;
|
||||
$cfg = file_exists($ram) ? my_parse_ini_file($ram, $sections, $scanner) : [];
|
||||
return file_exists($rom) ? array_replace_recursive($cfg, my_parse_ini_file($rom, $sections, $scanner)) : $cfg;
|
||||
}
|
||||
function parse_cron_cfg($plugin, $job, $text = "") {
|
||||
$cron = "/boot/config/plugins/$plugin/$job.cron";
|
||||
|
||||
@@ -25,9 +25,7 @@ setlocale(LC_ALL,'en_US.UTF-8');
|
||||
date_default_timezone_set(substr(readlink('/etc/localtime'),20));
|
||||
$secure = array_key_exists('HTTPS', $_SERVER);
|
||||
ini_set("session.use_strict_mode", "1");
|
||||
// Safari bug prevents use of 'Strict'
|
||||
// ini_set("session.cookie_samesite", $secure?'Strict':'Lax');
|
||||
ini_set("session.cookie_samesite", 'Lax');
|
||||
ini_set("session.cookie_samesite", 'Strict');
|
||||
if (array_key_exists('HTTP_HOST', $_SERVER)) {
|
||||
session_name("unraid_".md5(strstr($_SERVER['HTTP_HOST'].':', ':', true)));
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
$vfio = '/boot/config/vfio-pci.cfg';
|
||||
$old = is_file($vfio) ? rtrim(file_get_contents($vfio)) : '';
|
||||
$new = _var($_GET,'cfg');
|
||||
$new = _var($_POST,'cfg');
|
||||
|
||||
$reply = 0;
|
||||
if ($new != $old) {
|
||||
|
||||
@@ -78,25 +78,28 @@ function device_info(&$disk,$online) {
|
||||
$help .= "<br>"._("Click to spin $action device");
|
||||
}
|
||||
$status = "<a class='info'><i ".($ctrl?"id='dev-$named' ":"")."class='fa fa-$orb orb $color-orb'$ctrl></i><span>$help</span></a>";
|
||||
$link = (($parity || $data || $pool) && $disk_status!='DISK_NP') || $name=='flash' || in_array($name,$pools) || $type=='New'
|
||||
? "<a href=\"".htmlspecialchars("/Main/Settings/$source?name=$name")."\">$fancy</a>"
|
||||
|
||||
$link = ($parity && $disk_status!='DISK_NP_DSBL') || (($data || $pool) && $disk_status!='DISK_NP') || $name=='flash' || in_array($name,$pools) || $type=='New'
|
||||
? "<a href=\"".htmlspecialchars("/Main/$source?name=$name")."\">$fancy</a>"
|
||||
: $fancy;
|
||||
return $view.$status.$link;
|
||||
}
|
||||
function device_desc(&$disk) {
|
||||
global $var;
|
||||
$size = my_scale(_var($disk,'size',0)*1024 ?: _var($disk,'sectors',0)*_var($disk,'sector_size',0),$unit,-1,-1);
|
||||
switch (_var($disk,'type')) {
|
||||
case 'Flash': $type = 'usb'; break;
|
||||
case 'Parity': $type = _var($disk,'rotational') ? 'disk' : 'nvme'; break;
|
||||
case 'Data':
|
||||
case 'Cache': $type = _var($disk,'rotational') ? (_var($disk,'luksState') ? 'disk-encrypted' : 'disk') : 'nvme'; break;
|
||||
default: $type = 'disk'; break;
|
||||
$size = my_scale(_var($disk,'size',0)*1024 ?: _var($disk,'sectors',0)*_var($disk,'sector_size',0),$unit,-1);
|
||||
if (_var($var,'fsState')=='Started') {
|
||||
switch (_var($disk,'type')) {
|
||||
case 'Flash': $type = 'usb'; break;
|
||||
case 'Parity': $type = _var($disk,'rotational') ? 'disk' : 'nvme'; break;
|
||||
case 'Data':
|
||||
case 'Cache': $type = _var($disk,'rotational') ? (_var($disk,'luksState') ? 'disk-encrypted' : 'disk') : 'nvme'; break;
|
||||
default: $type = 'disk'; break;
|
||||
}
|
||||
$log = "<a class='info hand' onclick=\"openTerminal('disklog','"._var($disk,'device')."','')\"><i class='icon-$type icon'></i><span>"._('Disk Log Information')."</span></a>";
|
||||
return $log."<span style='font-family:bitstream'>".my_id(_var($disk,'id'))."</span> - $size $unit ("._var($disk,'device').")";
|
||||
} else {
|
||||
return my_id(_var($disk,'id'))." - $size $unit ("._var($disk,'device').")";
|
||||
}
|
||||
$log = _var($var,'fsState')=='Started'
|
||||
? "<a class='info hand' onclick=\"openTerminal('disklog','"._var($disk,'device')."','')\"><i class='icon-$type icon'></i><span>"._('Disk Log Information')."</span></a>"
|
||||
: "<a class='static'><i class='icon-$type icon'></i></a>";
|
||||
return $log."<span style='font-family:bitstream'>".my_id(_var($disk,'id'))."</span> - $size $unit ("._var($disk,'device').")";
|
||||
}
|
||||
function assignment(&$disk) {
|
||||
global $var, $devs;
|
||||
|
||||
@@ -101,11 +101,11 @@ while (true) {
|
||||
$vmencode = $lv->domain_get_uuid($vm);
|
||||
$echo[$vmencode ]['gcpu'] = "<span class='advanced'>"._("Guest CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuguest']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuguest']."%;'>  </span><span></span></div></span>";
|
||||
$echo[$vmencode ]['hcpu'] = "<span class='advanced'>"._("Host CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuhost']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuhost']."%;'>  </span><span></span></div></span>";
|
||||
$echo[$vmencode ]['mem'] = "<span>Mem: ".my_scale($vmdata['mem']*1024,$unit)."$unit / ".my_scale($vmdata['curmem']*1024,$unit)."$unit";
|
||||
$echo[$vmencode ]['mem'] = "<span>Mem: ".my_scale($vmdata['mem']*1024,$unit,null,null,1024)."$unit / ".my_scale($vmdata['curmem']*1024,$unit,null,null,1024)."$unit";
|
||||
if ($vmdata['maxmem'] == $vmdata['curmem']) $echo[$vmencode ]['mem'] .="  </span>";
|
||||
else $echo[$vmencode ]['mem'] .= " / ".my_scale($vmdata['maxmem']*1024,$unit)."$unit  </span>";
|
||||
$echo[$vmencode ]['disk'] = "<span>Disk: "._("Rd").": ".my_scale($vmdata['rdrate']/$timer,$unit)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate']/$timer,$unit)."$unit/s  </span>";
|
||||
$echo[$vmencode ]['net'] = "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate']/$timer,$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate']/$timer,$unit)."$unit/s  </span>";
|
||||
else $echo[$vmencode ]['mem'] .= " / ".my_scale($vmdata['maxmem']*1024,$unit,null,null,1024)."$unit  </span>";
|
||||
$echo[$vmencode ]['disk'] = "<span>Disk: "._("Rd").": ".my_scale($vmdata['rdrate']/$timer,$unit,null,null,1024)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate']/$timer,$unit,null,null,1024)."$unit/s  </span>";
|
||||
$echo[$vmencode ]['net'] = "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate']/$timer,$unit,null,null,1024)."$unit/s "._("TX").": ".my_scale($vmdata['txrate']/$timer,$unit,null,null,1024)."$unit/s  </span>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -438,6 +438,7 @@ file_put_contents("/$diag/system/loads.txt",$cpuload.implode("\r\n",$loadTxt));
|
||||
run("lscpu 2>/dev/null|todos >".escapeshellarg("/$diag/system/lscpu.txt"));
|
||||
run("lsscsi -vgl 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsscsi.txt"));
|
||||
run("lspci -knn 2>/dev/null|todos >".escapeshellarg("/$diag/system/lspci.txt"));
|
||||
run("lspci -vv 2>/dev/null| awk '/ASPM/{print $0}' RS=|grep -P '(^[a-z0-9:.]+|ASPM |Disabled;|Enabled;)'|todos >".escapeshellarg("/$diag/system/aspm-status.txt"));
|
||||
run("lsusb 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsusb.txt"));
|
||||
run("free -mth 2>/dev/null|todos >".escapeshellarg("/$diag/system/memory.txt"));
|
||||
run("lsof -Pni 2>/dev/null|todos >".escapeshellarg("/$diag/system/lsof.txt"));
|
||||
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
#!/bin/bash
|
||||
# Usage:
|
||||
# apply|nfs_version|nfs_count
|
||||
#
|
||||
|
||||
apply() {
|
||||
echo "RPC_NFSD_VERS=\"$RPC_NFSD_VERS\"" > $CONFIG_RAM
|
||||
echo "RPC_NFSD_COUNT=\"$RPC_NFSD_COUNT\"" >> $CONFIG_RAM
|
||||
if /etc/rc.d/rc.nfsd status >/dev/null ; then
|
||||
/etc/rc.d/rc.nfsd restart
|
||||
fi
|
||||
}
|
||||
|
||||
nfs_version() {
|
||||
echo $RPC_NFSD_VERS
|
||||
}
|
||||
|
||||
nfs_count() {
|
||||
echo $RPC_NFSD_COUNT
|
||||
}
|
||||
|
||||
# Path to the configuration files
|
||||
CONFIG_ROM="/etc/default/nfs"
|
||||
CONFIG_RAM="/boot/config/default/nfs"
|
||||
|
||||
# Get current settings
|
||||
source "$CONFIG_ROM"
|
||||
|
||||
case "$1" in
|
||||
'apply')
|
||||
RPC_NFSD_VERS="$2"
|
||||
RPC_NFSD_COUNT="$3"
|
||||
apply
|
||||
;;
|
||||
'nfs_version')
|
||||
nfs_version
|
||||
;;
|
||||
'nfs_count')
|
||||
nfs_count
|
||||
;;
|
||||
*)
|
||||
echo "usage $0 apply|nfs_version|nfs_count"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -145,7 +145,7 @@ span.link{text-decoration:underline;cursor:pointer}
|
||||
</style>
|
||||
|
||||
<table class='info'>
|
||||
<tr><td><?=_('Model')?>:</td><td><?=$model?></td></tr>
|
||||
<tr><td><?=_('Model')?>:</td><td><?=htmlspecialchars($model)?></td></tr>
|
||||
<tr><td><?=('M/B')?>:</td><td><?="{$board['Manufacturer']} {$board['Product Name']} {$board['Version']} {$board['Serial Number']}"?></td></tr>
|
||||
<tr><td><?=_('BIOS')?>:</td><td><?="{$bios['Vendor']} {$bios['Version']} {$bios['Release Date']}"?></td></tr>
|
||||
<tr><td><?=_('CPU')?>:</td><td><?="$cpumodel {$cpu['Current Speed']}"?></td></tr>
|
||||
|
||||
@@ -63,7 +63,7 @@ foreach (glob('plugins/*', GLOB_ONLYDIR) as $plugin) {
|
||||
}
|
||||
|
||||
// Get general variables
|
||||
$name = untangle(_var($_GET,'name'));
|
||||
$name = rawurldecode(_var($_GET,'name'));
|
||||
$dir = rawurldecode(_var($_GET,'dir'));
|
||||
$path = substr(strtok(_var($_SERVER,'REQUEST_URI'),'?'),1);
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Redirect Page</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="text" style="text-align: center; margin-top: calc(100vh - 75%); display: none; font-family: sans-serif;">
|
||||
<h1>Redirecting...</h1>
|
||||
|
||||
<h2><a id="redirectButton" href="/Main">Click here if you are not redirected automatically</a></h2>
|
||||
</div>
|
||||
<div>
|
||||
</div>
|
||||
<script>
|
||||
function parseRedirectTarget(target) {
|
||||
if (target && target !== '/') {
|
||||
// parse target and ensure it is a bare path with no query parameters
|
||||
const url = new URL(target, window.location.origin);
|
||||
return url.pathname;
|
||||
}
|
||||
return '/Main';
|
||||
}
|
||||
|
||||
function getRedirectUrl() {
|
||||
const search = new URLSearchParams(window.location.search);
|
||||
const targetRoute = parseRedirectTarget(search.get('target'));
|
||||
if (search.has('data') && (search.size === 1 || search.size === 2)) {
|
||||
return `${window.location.origin}${targetRoute}?data=${encodeURIComponent(search.get('data'))}`;
|
||||
}
|
||||
return `${window.location.origin}${targetRoute}`;
|
||||
}
|
||||
|
||||
function showText() {
|
||||
document.getElementById('text').style.display = 'block';
|
||||
}
|
||||
|
||||
document.getElementById('redirectButton').attributes.href.value = getRedirectUrl();
|
||||
|
||||
setTimeout(() => {
|
||||
showText();
|
||||
}, 750);
|
||||
window.location.href = getRedirectUrl();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
+13
-8
@@ -130,11 +130,10 @@ bzcheck(){
|
||||
}
|
||||
|
||||
bzmount(){
|
||||
local BZFILE=$1
|
||||
local MNTDIR=$2
|
||||
bzcheck $BZFILE
|
||||
/bin/mkdir -p /$MNTDIR
|
||||
/sbin/mount -v -r -t squashfs /boot/$BZFILE /$MNTDIR || abort "cannot mount $BZFILE"
|
||||
local BZDIR=$1
|
||||
local BZFILE=$2
|
||||
local MNTDIR=$3
|
||||
/sbin/mount -v -r -t squashfs /$BZDIR/$BZFILE /$MNTDIR || abort "cannot mount /$BZDIR/$BZFILE"
|
||||
# setup an overlayfs
|
||||
/bin/mkdir -p /var/local/overlay/$MNTDIR
|
||||
/bin/mkdir -p /var/local/overlay-work/$MNTDIR
|
||||
@@ -145,9 +144,15 @@ if [[ $UNRAIDROOT == "" ]]; then
|
||||
bzcheck "bzimage"
|
||||
bzcheck "bzroot"
|
||||
bzcheck "bzroot-gui"
|
||||
|
||||
bzmount "bzmodules" "lib"
|
||||
bzmount "bzfirmware" "usr"
|
||||
bzcheck "bzmodules"
|
||||
bzcheck "bzfirmware"
|
||||
if [[ -f /boot/config/fastusr ]]; then
|
||||
/bin/cp /boot/bzfirmware /usr
|
||||
bzmount "usr" "bzfirmware" "usr"
|
||||
else
|
||||
bzmount "boot" "bzfirmware" "usr"
|
||||
fi
|
||||
bzmount "boot" "bzmodules" "lib"
|
||||
|
||||
# now that /usr is mounted make /etc/rc.d a symlink
|
||||
/bin/rm -rf /etc/rc.d
|
||||
|
||||
@@ -52,6 +52,7 @@ rm -rf /kernel
|
||||
# Ensure required config directories exist
|
||||
# these will all have permissions 0700
|
||||
CONFIG="/boot/config"
|
||||
mkdir -p $CONFIG/default
|
||||
mkdir -p $CONFIG/modprobe.d
|
||||
mkdir -p $CONFIG/plugins/dockerMan
|
||||
mkdir -p $CONFIG/plugins/dynamix/users
|
||||
@@ -150,6 +151,8 @@ obsolete "NerdPack" "2021.08.11"
|
||||
obsolete "upnp-monitor" "2020.01.04c"
|
||||
# ZFS-Companion Monitor by campusantu, breaks the dashboard
|
||||
obsolete "ZFS-companion" "2021.08.24"
|
||||
# Folder View - Latest versions are only compatible with 7.x Older versions have issues
|
||||
obsolete "folder.view" "2024.10.02"
|
||||
|
||||
# If "unraidsafemode" indicated, skip installing extra packages and plugins
|
||||
if [[ -f /boot/unraidsafemode ]] || grep -wq unraidsafemode /proc/cmdline; then
|
||||
|
||||
+17
-11
@@ -18,9 +18,10 @@ NFSD="/usr/sbin/rpc.nfsd"
|
||||
EXPORTFS="/usr/sbin/exportfs"
|
||||
RQUOTAD="/usr/sbin/rpc.rquotad"
|
||||
MOUNTD="/usr/sbin/rpc.mountd"
|
||||
OPTIONS="-u -s"
|
||||
RPC="/etc/default/rpc"
|
||||
NFS="/etc/default/nfs"
|
||||
RPC_CFG="/boot/config/default/rpc"
|
||||
NFS_CFG="/boot/config/default/nfs"
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
@@ -28,14 +29,23 @@ NFS="/etc/default/nfs"
|
||||
# library functions
|
||||
. /etc/rc.d/rc.library.source
|
||||
|
||||
# source default settings
|
||||
[[ -r $RPC ]] && . $RPC
|
||||
[[ -r $RPC_CFG ]] && . $RPC_CFG
|
||||
|
||||
[[ -r $NFS ]] && . $NFS
|
||||
[[ -r $NFS_CFG ]] && . $NFS_CFG
|
||||
sed -ri "s/^(RPC_NFSD_VERS)=.*/\1=\"$RPC_NFSD_VERS\"/" $NFS 2>/dev/null
|
||||
sed -ri "s/^(RPC_NFSD_XPORT)=.*/\1=\"$RPC_NFSD_XPORT\"/" $NFS 2>/dev/null
|
||||
sed -ri "s/^(RPC_NFSD_OPTS)=.*/\1=\"$RPC_NFSD_OPTS\"/" $NFS 2>/dev/null
|
||||
sed -ri "s/^(RPC_NFSD_COUNT)=.*/\1=\"$RPC_NFSD_COUNT\"/" $NFS 2>/dev/null
|
||||
|
||||
# get bind addresses
|
||||
if check && [[ -n $BIND ]]; then
|
||||
RPC_NFSD_OPTS="$OPTIONS -H ${BIND// / -H }"
|
||||
RPC_NFSD_BIND="-H ${BIND// / -H }"
|
||||
sed -ri "s/^(RPC_NFSD_BIND)=.*/\1=\"$RPC_NFSD_BIND\"/" $NFS 2>/dev/null
|
||||
fi
|
||||
|
||||
# source default settings:
|
||||
[[ -r $RPC ]] && . $RPC
|
||||
|
||||
nfsd_running(){
|
||||
sleep 0.1
|
||||
ps axc | grep -q rpc.mountd
|
||||
@@ -81,13 +91,9 @@ nfsd_start(){
|
||||
[[ -n $RPC_RQUOTAD_PORT ]] && RPC_RQUOTAD_OPTS="$RPC_RQUOTAD_OPTS -p $RPC_RQUOTAD_PORT"
|
||||
run $RQUOTAD $RPC_RQUOTAD_OPTS
|
||||
fi
|
||||
# update default settings
|
||||
sed -ri "s/^(RPC_NFSD_OPTS)=.*/\1=\"$RPC_NFSD_OPTS\"/" $NFS 2>/dev/null
|
||||
[[ -r $NFS ]] && . $NFS
|
||||
# start nfsd servers - 8 if not set extrawise (an old Sun standard):
|
||||
# start nfsd servers
|
||||
if [[ -x $NFSD ]]; then
|
||||
[[ -z $RPC_NFSD_COUNT ]] && RPC_NFSD_COUNT=8
|
||||
run $NFSD $RPC_NFSD_OPTS $RPC_NFSD_COUNT
|
||||
run $NFSD $RPC_NFSD_VERS $RPC_NFSD_XPORT $RPC_NFSD_BIND $RPC_NFSD_OPTS $RPC_NFSD_COUNT
|
||||
fi
|
||||
if [[ -x $MOUNTD ]]; then
|
||||
[[ -n $RPC_MOUNTD_PORT ]] && RPC_MOUNTD_OPTS="$RPC_MOUNTD_OPTS -p $RPC_MOUNTD_PORT"
|
||||
|
||||
@@ -459,6 +459,13 @@ build_locations(){
|
||||
allow all;
|
||||
}
|
||||
#
|
||||
# redirect.htm available without authentication
|
||||
#
|
||||
location = /redirect {
|
||||
rewrite ^ /redirect.htm break;
|
||||
allow all;
|
||||
}
|
||||
#
|
||||
# proxy update.htm and logging.htm scripts to emhttpd listening on local socket
|
||||
#
|
||||
location = /update.htm {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Copyright 2024, Lime Technology
|
||||
# Copyright 2024, Christoph Hummer
|
||||
# Copyright 2024-2025, Lime Technology
|
||||
# Copyright 2024-2025, Christoph Hummer
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -18,10 +18,12 @@ exec_entrypoint() {
|
||||
}
|
||||
|
||||
error_handler() {
|
||||
echo "ERROR: Unraid Docker Hook script throw an error!"
|
||||
echo " Starting container without Tailscale!"
|
||||
echo
|
||||
exec_entrypoint
|
||||
if [ "${DISABLE_ERROR_HANDLER}" != "true" ]; then
|
||||
echo "ERROR: Unraid Docker Hook script throw an error!"
|
||||
echo " Starting container without Tailscale!"
|
||||
echo
|
||||
exec_entrypoint
|
||||
fi
|
||||
}
|
||||
|
||||
echo "======================="
|
||||
@@ -34,7 +36,14 @@ if [ "$(id -u)" != "0" ]; then
|
||||
error_handler
|
||||
fi
|
||||
|
||||
if [ ! -f /usr/bin/tailscale ] || [ ! -f /usr/bin/tailscaled ]; then
|
||||
if [ -f /usr/local/bin/tailscale ] || [ -f /usr/local/bin/tailscaled ]; then
|
||||
echo "Official Tailscale Sidecar container detected!"
|
||||
echo
|
||||
OFFICIAL_TS_SIDECAR="true"
|
||||
apk update >/dev/null 2>&1
|
||||
apk add jq >/dev/null 2>&1
|
||||
elif [ ! -f /usr/bin/tailscale ] || [ ! -f /usr/bin/tailscaled ]; then
|
||||
OFFICIAL_TS_SIDECAR="false"
|
||||
if [ ! -z "${TAILSCALE_EXIT_NODE_IP}" ]; then
|
||||
if [ ! -c /dev/net/tun ]; then
|
||||
echo "ERROR: Device /dev/net/tun not found!"
|
||||
@@ -78,7 +87,7 @@ if [ ! -f /usr/bin/tailscale ] || [ ! -f /usr/bin/tailscaled ]; then
|
||||
if [ ! -z "${PACKAGES_UPDATE}" ]; then
|
||||
UPDATE_LOG=$(${PACKAGES_UPDATE} 2>&1)
|
||||
fi
|
||||
INSTALL_LOG=$(${PACKAGES_INSTALL} jq wget ${INSTALL_IPTABLES}${PACKAGES_TROUBLESHOOTING} 2>&1)
|
||||
INSTALL_LOG=$(${PACKAGES_INSTALL} jq wget ca-certificates ${INSTALL_IPTABLES}${PACKAGES_TROUBLESHOOTING} 2>&1)
|
||||
INSTALL_RESULT=$?
|
||||
|
||||
if [ "${INSTALL_RESULT}" -eq 0 ]; then
|
||||
@@ -128,13 +137,22 @@ if [ ! -f /usr/bin/tailscale ] || [ ! -f /usr/bin/tailscaled ]; then
|
||||
|
||||
echo "Installation Done!"
|
||||
else
|
||||
OFFICIAL_TS_SIDECAR="false"
|
||||
echo "Tailscale found, continuing..."
|
||||
fi
|
||||
|
||||
unset TSD_PARAMS
|
||||
unset TS_PARAMS
|
||||
|
||||
if [ ! -z "${TAILSCALE_STATE_DIR}" ]; then
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" = "true" ]; then
|
||||
if [ -z "${TS_STATE_DIR}" ]; then
|
||||
echo "No Tailscale State Directory specified, falling back to: /var/lib/tailscale"
|
||||
export TS_STATE_DIR="/var/lib/tailscale"
|
||||
else
|
||||
export TS_STATE_DIR="${TS_STATE_DIR}"
|
||||
fi
|
||||
TSD_STATE_DIR="${TS_STATE_DIR}"
|
||||
elif [ ! -z "${TAILSCALE_STATE_DIR}" ]; then
|
||||
TSD_STATE_DIR="${TAILSCALE_STATE_DIR}"
|
||||
elif [ ! -z "${SERVER_DIR}" ]; then
|
||||
TSD_STATE_DIR="${SERVER_DIR}/.tailscale_state"
|
||||
@@ -146,6 +164,8 @@ elif [ -d "/config" ]; then
|
||||
TSD_STATE_DIR="/config/.tailscale_state"
|
||||
elif [ -d "/data" ]; then
|
||||
TSD_STATE_DIR="/data/.tailscale_state"
|
||||
elif [ ! -z "${CA_TS_FALLBACK_DIR}" ]; then
|
||||
TSD_STATE_DIR="${CA_TS_FALLBACK_DIR}/.tailscale_state"
|
||||
else
|
||||
echo "ERROR: Couldn't detect persistent Docker directory for .tailscale_state!"
|
||||
echo " Please enable Tailscale Advanced Settings in the Docker template and set the Tailscale State Directory manually!"
|
||||
@@ -153,7 +173,7 @@ else
|
||||
fi
|
||||
echo "Settings Tailscale state dir to: ${TSD_STATE_DIR}"
|
||||
|
||||
if [ ! -d "${TSD_STATE_DIR}" ]; then
|
||||
if [ ! -z "${TSD_STATE_DIR}" ] && [ ! -d "${TSD_STATE_DIR}" ]; then
|
||||
mkdir -p ${TSD_STATE_DIR}
|
||||
fi
|
||||
|
||||
@@ -195,12 +215,14 @@ if [ "${TAILSCALE_USE_SSH}" = "true" ]; then
|
||||
TS_PARAMS="${TS_PARAMS} --ssh"
|
||||
fi
|
||||
|
||||
if [ "${TAILSCALE_LOG}" != "false" ]; then
|
||||
TSD_PARAMS="${TSD_PARAMS} >>/var/log/tailscaled 2>&1 "
|
||||
TSD_MSG=" with log file location: /var/log/tailscaled"
|
||||
else
|
||||
TSD_PARAMS="${TSD_PARAMS} >/dev/null 2>&1 "
|
||||
TSD_MSG=" with logging disabled"
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" != "true" ]; then
|
||||
if [ "${TAILSCALE_LOG}" != "false" ]; then
|
||||
TSD_PARAMS="${TSD_PARAMS} >>/var/log/tailscaled 2>&1 "
|
||||
TSD_MSG=" with log file location: /var/log/tailscaled"
|
||||
else
|
||||
TSD_PARAMS="${TSD_PARAMS} >/dev/null 2>&1 "
|
||||
TSD_MSG=" with logging disabled"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -z "${TAILSCALE_HOSTNAME}" ]; then
|
||||
@@ -209,35 +231,72 @@ if [ ! -z "${TAILSCALE_HOSTNAME}" ]; then
|
||||
TS_PARAMS="${TS_PARAMS} --hostname=${TAILSCALE_HOSTNAME}"
|
||||
fi
|
||||
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" = "true" ]; then
|
||||
if [ ! -z "${TAILSCALE_HOSTNAME}" ]; then
|
||||
export TS_STATE_DIR="${TS_STATE_DIR}/${TAILSCALE_HOSTNAME}"
|
||||
TSD_STATE_DIR="${TS_STATE_DIR}/${TAILSCALE_HOSTNAME}"
|
||||
else
|
||||
export TS_STATE_DIR="${TS_STATE_DIR}/$(hostname)"
|
||||
TSD_STATE_DIR="${TS_STATE_DIR}/$(hostname)"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "${TAILSCALE_EXIT_NODE}" = "true" ]; then
|
||||
echo "Configuring container as Exit Node! See https://tailscale.com/kb/1103/exit-nodes"
|
||||
TS_PARAMS="${TS_PARAMS} --advertise-exit-node"
|
||||
fi
|
||||
|
||||
if [ ! -z "${TAILSCALED_PARAMS}" ]; then
|
||||
TSD_PARAMS="${TAILSCALED_PARAMS} ${TSD_PARAMS}"
|
||||
fi
|
||||
|
||||
if [ ! -z "${TAILSCALE_PARAMS}" ]; then
|
||||
TS_PARAMS="${TAILSCALE_PARAMS}${TS_PARAMS}"
|
||||
fi
|
||||
|
||||
echo "Starting tailscaled${TSD_MSG}"
|
||||
eval tailscaled -statedir=${TSD_STATE_DIR} ${TSD_PARAMS}&
|
||||
|
||||
echo "Starting tailscale"
|
||||
eval tailscale up ${TS_PARAMS} --reset
|
||||
EXIT_STATUS="$?"
|
||||
|
||||
if [ "${EXIT_STATUS}" != "0" ]; then
|
||||
echo "ERROR: Connecting to Tailscale not successful!"
|
||||
if [ -f /var/log/tailscaled ]; then
|
||||
echo "Please check the logs:"
|
||||
tail -20 /var/log/tailscaled
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" = "true" ]; then
|
||||
if [ ! -z "${TAILSCALED_PARAMS}" ]; then
|
||||
export TS_TAILSCALED_EXTRA_ARGS="${TAILSCALED_PARAMS} ${TSD_PARAMS}"
|
||||
else
|
||||
export TS_TAILSCALED_EXTRA_ARGS="${TSD_PARAMS}"
|
||||
fi
|
||||
if [ ! -z "${TAILSCALE_PARAMS}" ]; then
|
||||
export TS_EXTRA_ARGS="${TAILSCALE_PARAMS}${TS_PARAMS}"
|
||||
else
|
||||
export TS_EXTRA_ARGS="${TS_PARAMS}"
|
||||
fi
|
||||
exec_entrypoint &
|
||||
TAILSCALE_PID=$!
|
||||
else
|
||||
if [ ! -z "${TAILSCALED_PARAMS}" ]; then
|
||||
TSD_PARAMS="${TAILSCALED_PARAMS} ${TSD_PARAMS}"
|
||||
fi
|
||||
if [ ! -z "${TAILSCALE_PARAMS}" ]; then
|
||||
TS_PARAMS="${TAILSCALE_PARAMS}${TS_PARAMS}"
|
||||
fi
|
||||
error_handler
|
||||
fi
|
||||
unset EXIT_STATUS
|
||||
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" != "true" ]; then
|
||||
echo "Starting tailscaled${TSD_MSG}"
|
||||
eval tailscaled -statedir=${TSD_STATE_DIR} ${TSD_PARAMS}&
|
||||
|
||||
echo "Starting tailscale"
|
||||
eval tailscale up ${TS_PARAMS} --reset
|
||||
EXIT_STATUS="$?"
|
||||
|
||||
if [ "${EXIT_STATUS}" != "0" ]; then
|
||||
echo "ERROR: Connecting to Tailscale not successful!"
|
||||
if [ -f /var/log/tailscaled ]; then
|
||||
echo "Please check the logs:"
|
||||
tail -20 /var/log/tailscaled
|
||||
fi
|
||||
error_handler
|
||||
fi
|
||||
unset EXIT_STATUS
|
||||
else
|
||||
DISABLE_ERROR_HANDLER="true"
|
||||
sleep 2
|
||||
fi
|
||||
|
||||
while true; do
|
||||
TAILSCALE_ONLINE=$(tailscale status --json | jq '.Self.Online')
|
||||
if [ "${TAILSCALE_ONLINE}" = "true" ]; then
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
if [ ! -z "${TAILSCALE_SERVE_PORT}" ] && [ "$(tailscale status --json | jq -r '.CurrentTailnet.MagicDNSEnabled')" != "false" ] && [ -z "$(tailscale status --json | jq -r '.Self.Capabilities[] | select(. == "https")')" ]; then
|
||||
echo "ERROR: Enable MagicDNS and HTTPS on your Tailscale account to use Tailscale Serve/Funnel."
|
||||
@@ -318,7 +377,7 @@ if [ ! -z "${TAILSCALE_SERVE_PORT}" ]; then
|
||||
echo "Generating Tailscale certs! This can take some time, please wait..."
|
||||
timeout 30 tailscale cert --cert-file="${TSD_STATE_DIR}/certs/${TS_DNSNAME}.crt" --key-file="${TSD_STATE_DIR}/certs/${TS_DNSNAME}.key" "${TS_DNSNAME}" >/dev/null 2>&1
|
||||
EXIT_STATUS="$?"
|
||||
if [ "${EXIT_STATUS}" != "0" ]; then
|
||||
if [ "${EXIT_STATUS}" != "0" ] && [ "${OFFICIAL_TS_SIDECAR}" != "true" ]; then
|
||||
echo "ERROR: Can't generate certificates!"
|
||||
echo "Please check the logs:"
|
||||
tail -10 /var/log/tailscaled
|
||||
@@ -330,4 +389,9 @@ if [ ! -z "${TAILSCALE_SERVE_PORT}" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
exec_entrypoint
|
||||
if [ "${OFFICIAL_TS_SIDECAR}" != "true" ]; then
|
||||
exec_entrypoint
|
||||
else
|
||||
trap "kill -SIGTERM ${TAILSCALE_PID}; exit 0" SIGTERM
|
||||
wait "${TAILSCALE_PID}"
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user