Compare commits
106 Commits
feat/css3-
...
fix-typo
Author | SHA1 | Date | |
---|---|---|---|
|
043d2baaf7 | ||
|
c9333ea955 | ||
|
bad23e7647 | ||
17909f889e | |||
8cabad6f0d | |||
|
566113f86c | ||
|
21e640184e | ||
|
202196f7d3 | ||
9c2aa45751 | |||
|
06735f7a3e | ||
|
e7f7ef43c0 | ||
|
c5b692e805 | ||
|
6a91f270e3 | ||
|
6d3a7a3298 | ||
f81118ffe3 | |||
f9107ebe11 | |||
76f58d2995 | |||
b4722f57aa | |||
3314860d31 | |||
9a6b62ae98 | |||
e0b1612633 | |||
1e41ac637d | |||
858a3aa999 | |||
79c484e2e5 | |||
49793ff602 | |||
342619a567 | |||
|
27047c8832 | ||
|
b850940f19 | ||
|
de3334b0d2 | ||
|
373bb9f2ee | ||
|
833194705c | ||
|
392cc77a20 | ||
|
d272bf78ac | ||
|
9430366eaf | ||
|
71dc414592 | ||
|
2b41f9a8d2 | ||
|
70c01ec454 | ||
|
7840ae6d3c | ||
|
5b009dfb39 | ||
|
5565c02f74 | ||
|
793289bc7f | ||
|
7d92761860 | ||
|
1021adc33b | ||
|
c9374f7911 | ||
|
73a17a0306 | ||
|
0729386af9 | ||
|
4b8ec6e5a3 | ||
|
ea2fa8a8db | ||
|
d7e474257c | ||
|
4b3e8f2d46 | ||
|
54a6e3dd13 | ||
|
e20f37d936 | ||
|
4c1c566e78 | ||
|
a6c50b208a | ||
|
9a23761dc8 | ||
|
359334b85a | ||
|
f5ed6964dd | ||
|
882ee7f911 | ||
|
234a749b7f | ||
|
a9891f557e | ||
|
04640a5708 | ||
|
fac92be4d4 | ||
|
817ed5c1c1 | ||
|
a4abe0fa55 | ||
|
6920542d6c | ||
|
36f9e7402c | ||
|
cfa547972e | ||
|
84b5baf402 | ||
|
1b162e2c21 | ||
|
75f0c2e4f6 | ||
|
67369622fa | ||
|
17fdfb6f50 | ||
|
9e80fb13c7 | ||
|
1d6c3f4375 | ||
58c31f4ef6 | |||
|
84b767ddcd | ||
|
32d3f88b44 | ||
|
6156a2582f | ||
|
8a55228b8e | ||
|
fe7ab1fc43 | ||
30492ed2f2 | |||
da1ef5c0e0 | |||
93054c2091 | |||
|
f2abfaf292 | ||
|
5a42314c60 | ||
|
bbed6047e3 | ||
|
a7f6ac7389 | ||
|
f7748f7619 | ||
|
d4968e1b19 | ||
|
fb680469ac | ||
|
eaabbec7e0 | ||
|
693a0260af | ||
|
130c9c6373 | ||
73c264e9fe | |||
667741129a | |||
|
42fe45595f | ||
|
ed9b8322d4 | ||
|
cfb2daa531 | ||
|
694d35b412 | ||
|
ffabb996fc | ||
|
4a4444229e | ||
|
083cd984ea | ||
|
3dda97319d | ||
|
064cac1110 | ||
|
3d1b53d0ea | ||
|
61e99a390e |
@@ -1 +0,0 @@
|
||||
/usr/libexec/unraid/firefox-119.0.r20231019122658-x86_64.AppImage
|
@@ -1 +0,0 @@
|
||||
/usr/libexec/unraid/unraidwold
|
@@ -1038,6 +1038,15 @@ You must specify a folder for Docker. The system will automatically create this
|
||||
It is recommended to create this folder under a share which resides on the Cache pool (setting: cache=Only). For best performance SSD devices are preferred.
|
||||
:end
|
||||
|
||||
:docker_storage_driver_help:
|
||||
overlay2 (default): Will use overlay2 as the storage driver for Docker, regardless of the underlying filesystem.
|
||||
|
||||
native: The native storage driver for your underlying filesystem will be used (XFS: overlay2 | ZFS: zfs | BTRFS: btrfs).
|
||||
|
||||
ATTENTION: Changing the storage type from an existing Docker installation is not possible, you have to delete your Docker directory first, change the storage type and then reinstall your containers.
|
||||
It is recommended to take a screenshot from your Docker containers before changing the storage type. After deleting and changing the storage type, reinstall the containers by clicking Add Container on the Docker page and select one by one from the drop down to reinstall them with your previous settings).
|
||||
:end
|
||||
|
||||
:docker_appdata_location_help:
|
||||
You can specify a folder to automatically generate and store subfolders containing configuration files for each Docker app (via the /config mapped volume).
|
||||
|
||||
@@ -1119,6 +1128,10 @@ This is the active Docker version.
|
||||
This is the location of the Docker image.
|
||||
:end
|
||||
|
||||
:docker_storage_driver_active_help:
|
||||
This is the storage driver for Docker.
|
||||
:end
|
||||
|
||||
:docker_appdata_location_active_help:
|
||||
This is the storage location for Docker containers.
|
||||
:end
|
||||
@@ -2415,7 +2428,7 @@ Note to Cloudflare users: the Cloudflare proxy is designed for http traffic, it
|
||||
|
||||
:wg_local_server_uses_nat_help:
|
||||
When NAT is enabled, the server uses its own LAN address when forwarding traffic from the tunnel to other devices in the LAN network.
|
||||
Use this setting when no router modifications are desired, but this approach doesn't work with Docker containers using custom IP addressess.
|
||||
Use this setting when no router modifications are desired, but this approach doesn't work with Docker containers using custom IP addresses.
|
||||
|
||||
When NAT is disabled, the server uses the WireGuard tunnel address when forwarding traffic.
|
||||
In this case it is required that the default gateway (router) has a static route configured to refer tunnel address back to the server.
|
||||
|
@@ -14,10 +14,15 @@ Tag="battery-3"
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
?>
|
||||
<script>
|
||||
function getUPSstatus() {
|
||||
$.post('/plugins/dynamix.apcupsd/include/UPSstatus.php',{level:<?=$cfg['BATTERYLEVEL']?>,runtime:<?=$cfg['MINUTES']?>},function(data) {
|
||||
var batteryLevel = "<?= _var($cfg,'BATTERYLEVEL',0) ?>";
|
||||
var batteryRuntime = "<?= _var($cfg,'MINUTES',0) ?>";
|
||||
|
||||
$.post('/plugins/dynamix.apcupsd/include/UPSstatus.php',{level:batteryLevel,runtime:batteryRuntime},function(data) {
|
||||
data = data.split('\n');
|
||||
$('#ups_summary').html(data[0]);
|
||||
$('#ups_status').html(data[1]);
|
||||
|
@@ -31,8 +31,8 @@ $cpus = cpu_list();
|
||||
<link type="text/css" rel="stylesheet" href="<?autov("/plugins/dynamix.docker.manager/styles/style-$theme.css")?>">
|
||||
|
||||
<table id="docker_containers" class="tablesorter shift">
|
||||
<thead><tr><th><a id="resetsort" class="nohand" onclick="resetSorting()" title="_(Reset sorting)_"><i class="fa fa-th-list"></i></a>_(Application)_</th><th>_(Version)_</th><th>_(Network)_</th><th>_(Port Mappings)_ <small>(_(App to Host)_)</small></th><th>_(Volume Mappings)_ <small>(_(App to Host)_)</small></th><th class="load advanced">_(CPU & Memory load)_</th><th class="nine">_(Autostart)_</th><th class="five">_(Uptime)_</th></tr></thead>
|
||||
<tbody id="docker_list"><tr><td colspan='8'></td></tr></tbody>
|
||||
<thead><tr><th><a id="resetsort" class="nohand" onclick="resetSorting()" title="_(Reset sorting)_"><i class="fa fa-th-list"></i></a>_(Application)_</th><th>_(Version)_</th><th>_(Network)_</th><th>_(Container IP)_</th><th>_(Container Port)_</th><th>_(LAN IP:Port)_</th><th>_(Volume Mappings)_ <small>(_(App to Host)_)</small></th><th class="load advanced">_(CPU & Memory load)_</th><th class="nine">_(Autostart)_</th><th class="five">_(Uptime)_</th></tr></thead>
|
||||
<tbody id="docker_list"><tr><td colspan='9'></td></tr></tbody>
|
||||
</table>
|
||||
<input type="button" onclick="addContainer()" value="_(Add Container)_" style="display:none">
|
||||
<input type="button" onclick="startAll()" value="_(Start All)_" style="display:none">
|
||||
@@ -183,3 +183,4 @@ window.onunload = function(){
|
||||
dockerload.stop();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -103,6 +103,9 @@ function base_net($route) {
|
||||
return substr(explode('/',$route)[0],0,-2);
|
||||
}
|
||||
$bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
|
||||
|
||||
//Check if docker.cfg not exists
|
||||
$no_dockercfg = !is_file('/boot/config/docker.cfg');
|
||||
?>
|
||||
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
|
||||
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
|
||||
@@ -188,6 +191,23 @@ _(Docker directory)_:
|
||||
:docker_vdisk_directory_help:
|
||||
|
||||
</div>
|
||||
|
||||
<div markdown="1" id="backingfs_type" style="display:none">
|
||||
_(Docker storage driver)_:
|
||||
: <select id="DOCKER_BACKINGFS" name="DOCKER_BACKINGFS" onchange="updateBackingFS(this.value)">
|
||||
<?=mk_option(_var($dockercfg,'DOCKER_BACKINGFS'), 'native', _('native'))?>
|
||||
<?=mk_option(_var($dockercfg,'DOCKER_BACKINGFS'), 'overlay2', _('overlay2'))?>
|
||||
</select>
|
||||
<?if ($var['fsState'] != "Started"):?>
|
||||
<span id="WARNING_BACKINGFS" style="display:none;"><i class="fa fa-warning icon warning"></i>_(Only modify if this is a new installation since this can lead to unwanted behaviour!)_</span>
|
||||
<?elseif (is_dir(_var($dockercfg,'DOCKER_IMAGE_FILE'))):?>
|
||||
<span id="WARNING_BACKINGFS" style="display:none;"><i class="fa fa-warning icon warning"></i>_(Switching the Storage Driver requires to delete and rebuild the Docker directory manually!)_</span>
|
||||
<?endif;?>
|
||||
|
||||
:docker_storage_driver_help:
|
||||
|
||||
</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="^[^\\]*/$">
|
||||
<?if ($var['fsState'] != "Started"):?>
|
||||
@@ -418,6 +438,7 @@ _(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
|
||||
</div>
|
||||
<?else: /* DOCKER STARTED */?>
|
||||
|
||||
|
||||
_(Docker version)_:
|
||||
: <?$arrInfo = $DockerClient->getInfo(); echo $arrInfo['Version']?>
|
||||
|
||||
@@ -433,6 +454,11 @@ _(Docker directory)_:
|
||||
|
||||
:docker_vdisk_location_active_help:
|
||||
|
||||
_(Docker storage driver)_:
|
||||
: <?=_var($dockercfg,'DOCKER_BACKINGFS')?>
|
||||
|
||||
:docker_storage_driver_active_help:
|
||||
|
||||
_(Default appdata storage location)_:
|
||||
: <?=_var($dockercfg,'DOCKER_APP_CONFIG_PATH')?>
|
||||
|
||||
@@ -592,6 +618,9 @@ function prepareDocker(form) {
|
||||
$(form).find('input[name="DOCKER_IMAGE_FILE"]').val($('#DOCKER_IMAGE_TYPE').val()=='folder' ? $("#DOCKER_IMAGE_FILE2").val() : $("#DOCKER_IMAGE_FILE1").val());
|
||||
$("#DOCKER_IMAGE_FILE1").prop('disabled',true);
|
||||
$("#DOCKER_IMAGE_FILE2").prop('disabled',true);
|
||||
<?if ($no_dockercfg):?>
|
||||
$(form).find('input[name="DOCKER_BACKINGFS"]').val($('#DOCKER_IMAGE_TYPE').val()=='folder' ? $("#DOCKER_BACKINGFS").val() : $("#DOCKER_BACKINGFS").val('native'));
|
||||
<?endif;?>
|
||||
<?endif;?>
|
||||
$(form).find('input:hidden[name^="DOCKER_DHCP_"]').each(function(){
|
||||
var id = '#'+$(this).attr('name')+'_';
|
||||
@@ -860,6 +889,7 @@ function btrfsScrub(path) {
|
||||
function updateLocation(val) {
|
||||
var content1 = $("#DOCKER_IMAGE_FILE1");
|
||||
var content2 = $("#DOCKER_IMAGE_FILE2");
|
||||
var dropdown = $("#DOCKER_BACKINGFS");
|
||||
switch (val) {
|
||||
case 'xfs':
|
||||
var path = content2.val().split('/');
|
||||
@@ -867,15 +897,18 @@ function updateLocation(val) {
|
||||
content1.val((path.join('/') + '/docker-xfs.img'));
|
||||
$('#vdisk_file').show('slow');
|
||||
$('#vdisk_dir').hide('slow');
|
||||
$('#backingfs_type').hide();
|
||||
content1.prop('disabled',false).trigger('change');
|
||||
content2.prop('disabled',true);
|
||||
dropdown.val('native');
|
||||
break;
|
||||
case 'folder':
|
||||
var path = content2.val().split('/');
|
||||
if (path[path.length-1]=='') path.splice(-2,2); else path.splice(-1,1);
|
||||
content2.val(path.join('/') + '/docker/');
|
||||
content2.val(path.join('/'));
|
||||
$('#vdisk_file').hide('slow');
|
||||
$('#vdisk_dir').show('slow');
|
||||
$('#backingfs_type').show('slow');
|
||||
content1.prop('disabled',true);
|
||||
content2.prop('disabled',false).trigger('change');
|
||||
break;
|
||||
@@ -885,11 +918,23 @@ function updateLocation(val) {
|
||||
content1.val((path.join('/') + '/docker.img'));
|
||||
$('#vdisk_file').show('slow');
|
||||
$('#vdisk_dir').hide('slow');
|
||||
$('#backingfs_type').hide();
|
||||
content1.prop('disabled',false).trigger('change');
|
||||
content2.prop('disabled',true);
|
||||
dropdown.val('native');
|
||||
break;
|
||||
}
|
||||
}
|
||||
function updateBackingFS(val) {
|
||||
var backingfs = "<?= _var($dockercfg,'DOCKER_BACKINGFS') ?>";
|
||||
var warning = document.getElementById("WARNING_BACKINGFS");
|
||||
var checkbox = $(".deleteCheckbox");
|
||||
if (val !== backingfs) {
|
||||
warning.style.display = "inline";
|
||||
} else {
|
||||
warning.style.display = "none";
|
||||
}
|
||||
}
|
||||
function checkbox_state(value) {
|
||||
$.post('/plugins/dynamix.docker.manager/include/UpdateConfig.php',{action:'exist',name:value},function(state){state==0 ? $('.deleteLabel').fadeIn() : $('.deleteLabel').fadeOut();});
|
||||
}
|
||||
@@ -897,6 +942,7 @@ $(function() {
|
||||
<?if ($DockerStopped):?>
|
||||
if ($('#DOCKER_IMAGE_TYPE').val()=='folder') {
|
||||
$('#vdisk_dir').show();
|
||||
$('#backingfs_type').show();
|
||||
checkbox_state($("#DOCKER_IMAGE_FILE2").val());
|
||||
$("#DOCKER_IMAGE_FILE2").prop('disabled',false);
|
||||
} else {
|
||||
|
@@ -9,3 +9,4 @@ DOCKER_ALLOW_ACCESS=""
|
||||
DOCKER_TIMEOUT=10
|
||||
DOCKER_READMORE="yes"
|
||||
DOCKER_PID_LIMIT=""
|
||||
DOCKER_BACKINGFS="overlay2"
|
||||
|
@@ -49,11 +49,11 @@ $port = file_exists('/sys/class/net/br0') ? 'BR0' : (file_exists('/sys/class/net
|
||||
// Docker configuration file - guaranteed to exist
|
||||
$docker_cfgfile = '/boot/config/docker.cfg';
|
||||
if (file_exists($docker_cfgfile)) {
|
||||
exec("grep -Pom2 '_SUBNET_|_{$port}(_[0-9]+)?=' $docker_cfgfile",$cfg);
|
||||
if (isset($cfg[0]) && $cfg[0]=='_SUBNET_' && empty($cfg[1])) {
|
||||
# interface has changed, update configuration
|
||||
exec("sed -ri 's/_(BR0|BOND0|ETH0)(_[0-9]+)?=/_{$port}\\2=/' $docker_cfgfile");
|
||||
}
|
||||
exec("grep -Pom2 '_SUBNET_|_{$port}(_[0-9]+)?=' $docker_cfgfile",$cfg);
|
||||
if (isset($cfg[0]) && $cfg[0]=='_SUBNET_' && empty($cfg[1])) {
|
||||
# interface has changed, update configuration
|
||||
exec("sed -ri 's/_(BR0|BOND0|ETH0)(_[0-9]+)?=/_{$port}\\2=/' $docker_cfgfile");
|
||||
}
|
||||
}
|
||||
|
||||
$defaults = (array)@parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg");
|
||||
@@ -255,7 +255,7 @@ class DockerTemplates {
|
||||
$doc = new DOMDocument();
|
||||
$doc->load($file['path']);
|
||||
if ($name) {
|
||||
if ($doc->getElementsByTagName('Name')->item(0)->nodeValue !== $name) continue;
|
||||
if (@$doc->getElementsByTagName('Name')->item(0)->nodeValue !== $name) continue;
|
||||
}
|
||||
$TemplateRepository = DockerUtil::ensureImageTag($doc->getElementsByTagName('Repository')->item(0)->nodeValue??'');
|
||||
if ($TemplateRepository && $TemplateRepository==$Repository) {
|
||||
@@ -293,7 +293,7 @@ class DockerTemplates {
|
||||
}
|
||||
|
||||
public function getAllInfo($reload=false,$com=true,$communityApplications=false) {
|
||||
global $dockerManPaths, $host;
|
||||
global $driver, $dockerManPaths, $host;
|
||||
$DockerClient = new DockerClient();
|
||||
$DockerUpdate = new DockerUpdate();
|
||||
//$DockerUpdate->verbose = $this->verbose;
|
||||
@@ -307,9 +307,8 @@ class DockerTemplates {
|
||||
$tmp['paused'] = $ct['Paused'];
|
||||
$tmp['autostart'] = in_array($name,$autoStart);
|
||||
$tmp['cpuset'] = $ct['CPUset'];
|
||||
$tmp['url'] = $tmp['url'] ?? '';
|
||||
$tmp['url'] = $ct['Url'] ?? $tmp['url'] ?? '';
|
||||
// read docker label for WebUI & Icon
|
||||
if (isset($ct['Url']) && !$tmp['url']) $tmp['url'] = $ct['Url'];
|
||||
if (isset($ct['Icon'])) $tmp['icon'] = $ct['Icon'];
|
||||
if (isset($ct['Shell'])) $tmp['shell'] = $ct['Shell'];
|
||||
if (!$communityApplications) {
|
||||
@@ -322,8 +321,18 @@ class DockerTemplates {
|
||||
// non-templated webui, user specified
|
||||
$tmp['url'] = $webui;
|
||||
} else {
|
||||
$ip = ($ct['NetworkMode']=='host'||_var($port,'NAT')) ? $host : _var($port,'IP');
|
||||
if ($ct['NetworkMode']=='host') {
|
||||
$ip = $host;
|
||||
} elseif (isset($driver[$ct['NetworkMode']]) && ($driver[$ct['NetworkMode']] == 'ipvlan' || $driver[$ct['NetworkMode']] == 'macvlan')) {
|
||||
$ip = reset($ct['Networks'])['IPAddress'];
|
||||
} elseif (!is_null(_var($port,'PublicPort'))) {
|
||||
$ip = $host;
|
||||
} else {
|
||||
$ip = _var($port,'IP');
|
||||
}
|
||||
$tmp['url'] = $ip ? (strpos($tmp['url'],$ip)!==false ? $tmp['url'] : $this->getControlURL($ct, $ip, $tmp['url'])) : $tmp['url'];
|
||||
if (strpos($ct['NetworkMode'], 'container:') === 0)
|
||||
$tmp['url'] = '';
|
||||
}
|
||||
if ( ($tmp['shell'] ?? false) == false )
|
||||
$tmp['shell'] = $this->getTemplateValue($image, 'Shell');
|
||||
@@ -338,8 +347,12 @@ class DockerTemplates {
|
||||
$tmp['updated'] = var_export($DockerUpdate->getUpdateStatus($image),true);
|
||||
}
|
||||
if (!$com) $tmp['updated'] = 'undef';
|
||||
if (empty($tmp['template']) || $reload) $tmp['template'] = $this->getUserTemplate($name);
|
||||
if ($reload) $DockerUpdate->updateUserTemplate($name);
|
||||
if ($ct['Manager'] !== 'dockerman')
|
||||
$tmp['template'] = null;
|
||||
else if (empty($tmp['template']) || $reload) {
|
||||
$tmp['template'] = $this->getUserTemplate($name);
|
||||
if ($reload) $DockerUpdate->updateUserTemplate($name);
|
||||
}
|
||||
//$this->debug("\n$name");
|
||||
//foreach ($tmp as $c => $d) $this->debug(sprintf(' %-10s: %s', $c, $d));
|
||||
}
|
||||
@@ -897,7 +910,7 @@ class DockerClient {
|
||||
}
|
||||
|
||||
public function getDockerContainers() {
|
||||
global $driver;
|
||||
global $driver, $host;
|
||||
// Return cached values
|
||||
if (is_array($this::$containersCache)) return $this::$containersCache;
|
||||
$this::$containersCache = [];
|
||||
@@ -922,23 +935,43 @@ class DockerClient {
|
||||
$c['Icon'] = $info['Config']['Labels']['net.unraid.docker.icon'] ?? false;
|
||||
$c['Url'] = $info['Config']['Labels']['net.unraid.docker.webui'] ?? false;
|
||||
$c['Shell'] = $info['Config']['Labels']['net.unraid.docker.shell'] ?? false;
|
||||
$c['Manager'] = $info['Config']['Labels']['net.unraid.docker.managed'] ?? false;
|
||||
$c['Ports'] = [];
|
||||
$c['Networks'] = [];
|
||||
if ($id) $c['NetworkMode'] = $net.str_replace('/',':',DockerUtil::ctMap($id)?:'/???');
|
||||
if (isset($driver[$c['NetworkMode']])) {
|
||||
if ($driver[$c['NetworkMode']]=='bridge') {
|
||||
$ports = &$info['HostConfig']['PortBindings'];
|
||||
$nat = true;
|
||||
} elseif ($driver[$c['NetworkMode']]=='host') {
|
||||
$c['Ports']['host'] = ['host' => ''];
|
||||
} elseif ($driver[$c['NetworkMode']]=='ipvlan' || $driver[$c['NetworkMode']]=='macvlan') {
|
||||
$c['Ports']['vlan'] = ['vlan' => ''];
|
||||
} else {
|
||||
$ports = &$info['Config']['ExposedPorts'];
|
||||
$nat = false;
|
||||
}
|
||||
$ip = $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'];
|
||||
} else if (!$id) {
|
||||
$c['NetworkMode'] = DockerUtil::ctMap($c['NetworkMode']);
|
||||
$ports = &$info['Config']['ExposedPorts'];
|
||||
foreach($ct['NetworkSettings']['Networks'] as $netName => $netVals) {
|
||||
$i = $c['NetworkMode']=='host' ? $host : $netVals['IPAddress'];
|
||||
$c['Networks'][$netName] = [ 'IPAddress' => $i ];
|
||||
}
|
||||
}
|
||||
$ip = $c['NetworkMode']=='host' ? $host : $ct['NetworkSettings']['Networks'][$c['NetworkMode']]['IPAddress'] ?? null;
|
||||
$c['Networks'][$c['NetworkMode']] = [ 'IPAddress' => $ip ];
|
||||
$ports = (isset($ports) && is_array($ports)) ? $ports : [];
|
||||
foreach ($ports as $port => $value) {
|
||||
if (!isset($info['HostConfig']['PortBindings'][$port])) {
|
||||
continue;
|
||||
}
|
||||
[$PrivatePort, $Type] = array_pad(explode('/', $port),2,'');
|
||||
$c['Ports'][] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $nat ? $value[0]['HostPort'] : $PrivatePort, 'NAT' => $nat, 'Type' => $Type];
|
||||
$PublicPort = $info['HostConfig']['PortBindings']["$port"][0]['HostPort'] ?: null;
|
||||
$nat = ($driver[$c['NetworkMode']]=='bridge');
|
||||
if (array_key_exists($PrivatePort, $c['Ports']) && $Type != $c['Ports'][$PrivatePort]['Type'])
|
||||
$Type = $c['Ports'][$PrivatePort]['Type'] . '/' . $Type;
|
||||
$c['Ports'][$PrivatePort] = ['IP' => $ip, 'PrivatePort' => $PrivatePort, 'PublicPort' => $PublicPort, 'NAT' => $nat, 'Type' => $Type, 'Driver' => $driver[$c['NetworkMode']]];
|
||||
}
|
||||
ksort($c['Ports']);
|
||||
$this::$containersCache[] = $c;
|
||||
}
|
||||
array_multisort(array_column($this::$containersCache,'Name'), SORT_NATURAL|SORT_FLAG_CASE, $this::$containersCache);
|
||||
|
@@ -87,11 +87,32 @@ foreach ($containers as $ct) {
|
||||
$icon = $info['icon'] ?: '/plugins/dynamix.docker.manager/images/question.png';
|
||||
$image = substr($icon,-4)=='.png' ? "<img src='$icon?".filemtime("$docroot{$info['icon']}")."' class='img' onerror=this.src='/plugins/dynamix.docker.manager/images/question.png';>" : (substr($icon,0,5)=='icon-' ? "<i class='$icon img'></i>" : "<i class='fa fa-$icon img'></i>");
|
||||
$wait = var_split($autostart[array_search($name,$names)]??'',1);
|
||||
$ports = [];
|
||||
$networks = [];
|
||||
$network_ips = [];
|
||||
foreach($ct['Networks'] as $netName => $netVals) {
|
||||
$networks[] = $netName;
|
||||
$network_ips[] = $netVals['IPAddress'];
|
||||
}
|
||||
$ports_internal = [];
|
||||
$ports_external = [];
|
||||
foreach ($ct['Ports'] as $port) {
|
||||
$intern = $running ? ($ct['NetworkMode']=='host' ? $host : _var($port,'IP')) : $null;
|
||||
$extern = $running ? (_var($port,'NAT') ? $host : $intern) : $null;
|
||||
$ports[] = sprintf('%s:%s/%s<i class="fa fa-arrows-h" style="margin:0 6px"></i>%s:%s', $intern, _var($port,'PrivatePort'), strtoupper(_var($port,'Type')), $extern, _var($port,'PublicPort'));
|
||||
if (strpos($ct['NetworkMode'], 'container:') === 0)
|
||||
break;
|
||||
if (_var($port,'PublicPort') && _var($port,'Driver') == 'bridge')
|
||||
$ports_external[] = sprintf('%s:%s', $host, strtoupper(_var($port,'PublicPort')));
|
||||
if (isset($ct['Networks']['host'])) {
|
||||
$ports_external[] = sprintf('%s', $netVals['IPAddress']);
|
||||
$ports_internal[] = sprintf('%s', 'all');
|
||||
break;
|
||||
}
|
||||
if (isset($ct['Ports']['vlan'])) {
|
||||
$ports_external[] = sprintf('%s', $netVals['IPAddress']);
|
||||
$ports_internal[] = sprintf('%s', 'all');
|
||||
break;
|
||||
}
|
||||
if ((!isset($ct['Networks']['host'])) || (!isset($ct['Networks']['vlan']))) {
|
||||
$ports_internal[] = sprintf('%s:%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')));
|
||||
}
|
||||
}
|
||||
$paths = [];
|
||||
$ct['Volumes'] = is_array($ct['Volumes']) ? $ct['Volumes'] : [];
|
||||
@@ -141,8 +162,10 @@ foreach ($containers as $ct) {
|
||||
break;
|
||||
}
|
||||
echo "<div class='advanced'><i class='fa fa-info-circle fa-fw'></i> ".compress(_($version),12,0)."</div></td>";
|
||||
echo "<td>{$ct['NetworkMode']}</td>";
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'>".implode('<br>',$ports)."</span></td>";
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'> ".implode('<br>',$networks)."</span></td>";
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'> ".implode('<br>',$network_ips)."</span></td>";
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'>".implode('<br>',$ports_internal)."</span></td>";
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'>".implode('<br>',$ports_external)."</span></td>";
|
||||
echo "<td style='word-break:break-all'><span class='docker_readmore'>".implode('<br>',$paths)."</span></td>";
|
||||
echo "<td class='advanced'><span class='cpu-$id'>0%</span><div class='usage-disk mm'><span id='cpu-$id' style='width:0'></span><span></span></div>";
|
||||
echo "<br><span class='mem-$id'>0 / 0</span></td>";
|
||||
@@ -162,3 +185,4 @@ foreach ($images as $image) {
|
||||
}
|
||||
echo "\0".implode($docker)."\0".(pgrep('rc.docker')!==false ? 1:0);
|
||||
?>
|
||||
|
||||
|
@@ -12,11 +12,6 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
/* Read the docker configuration file. */
|
||||
$cfgfile = "/boot/config/docker.cfg";
|
||||
$config_ini = @parse_ini_file($cfgfile, true, INI_SCANNER_RAW);
|
||||
$cfg = ($config_ini !== false) ? $config_ini : [];
|
||||
|
||||
function addRoute($ct) {
|
||||
// add static route(s) for remote WireGuard access
|
||||
[$pid,$net] = array_pad(explode(' ',exec("docker inspect --format='{{.State.Pid}} {{.NetworkSettings.Networks}}' $ct")),2,'');
|
||||
@@ -242,7 +237,7 @@ function xmlSecurity(&$template) {
|
||||
}
|
||||
|
||||
function xmlToCommand($xml, $create_paths=false) {
|
||||
global $docroot, $var, $cfg, $driver;
|
||||
global $docroot, $var, $driver;
|
||||
$xml = xmlToVar($xml);
|
||||
$cmdName = strlen($xml['Name']) ? '--name='.escapeshellarg($xml['Name']) : '';
|
||||
$cmdPrivileged = strtolower($xml['Privileged'])=='true' ? '--privileged=true' : '';
|
||||
@@ -307,12 +302,17 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the docker configuration file. */
|
||||
$cfgfile = "/boot/config/docker.cfg";
|
||||
$config_ini = @parse_ini_file($cfgfile, true, INI_SCANNER_RAW);
|
||||
$docker_cfg = ($config_ini !== false) ? $config_ini : [];
|
||||
|
||||
// Add pid limit if user has not specified it as an extra parameter
|
||||
$pidsLimit = preg_match('/--pids-limit (\d+)/', $xml['ExtraParams'], $matches) ? $matches[1] : null;
|
||||
if ($pidsLimit === null) {
|
||||
$pid_limit = "--pids-limit ";
|
||||
if (($cfg['DOCKER_PID_LIMIT']??'') != "") {
|
||||
$pid_limit .= $cfg['DOCKER_PID_LIMIT'];
|
||||
if (($docker_cfg['DOCKER_PID_LIMIT']??'') != "") {
|
||||
$pid_limit .= $docker_cfg['DOCKER_PID_LIMIT'];
|
||||
} else {
|
||||
$pid_limit .= "2048";
|
||||
}
|
||||
@@ -515,9 +515,15 @@ function getAllocations() {
|
||||
$nat = $ip = false;
|
||||
$list['Name'] = $ct['Name'];
|
||||
foreach ($ct['Ports'] as $tmp) {
|
||||
$nat = $tmp['NAT'];
|
||||
$ip = $tmp['IP'];
|
||||
$port[] = $tmp['PublicPort'];
|
||||
if (isset($tmp['NAT'])) {
|
||||
$nat = $tmp['NAT'];
|
||||
}
|
||||
if (isset($tmp['IP'])) {
|
||||
$ip = $tmp['IP'];
|
||||
}
|
||||
if (isset($tmp['PublicPort'])) {
|
||||
$port[] = $tmp['PublicPort'];
|
||||
}
|
||||
}
|
||||
sort($port);
|
||||
$ip = $ct['NetworkMode']=='host'||$nat ? $host : ($ip ?: DockerUtil::myIP($ct['Name']) ?: '0.0.0.0');
|
||||
|
28
emhttp/plugins/dynamix.docker.manager/system/Docker
Executable file
28
emhttp/plugins/dynamix.docker.manager/system/Docker
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
# Get active containers
|
||||
ACTIVE_CONTAINERS="$(docker ps -q --no-trunc 2>/dev/null)"
|
||||
|
||||
# Exit if no containers are active and return zero
|
||||
if [ -z "${ACTIVE_CONTAINERS}" ]; then
|
||||
echo "0"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Get all relevant memory entries from containers
|
||||
for container in ${ACTIVE_CONTAINERS} ; do
|
||||
CONT_MEMORY="$(cat /sys/fs/cgroup/docker/${container}/memory.stat 2>/dev/null | grep -Ew "anon|kernel|kernel_stack|pagetables|sec_pagetables|percpu|sock|vmalloc|shmem" | awk '{print $2}')"
|
||||
# Add up memory values
|
||||
for value in ${CONT_MEMORY} ; do
|
||||
if [[ ${value} =~ ^[0-9]+$ ]]; then
|
||||
((MEMORY_USAGE += value))
|
||||
fi
|
||||
done
|
||||
unset CONT_MEMORY
|
||||
done
|
||||
|
||||
# Check if value is a integer and return the value otherwiese return zero
|
||||
if [[ ${MEMORY_USAGE} =~ ^[0-9]+$ ]]; then
|
||||
echo "${MEMORY_USAGE}"
|
||||
else
|
||||
echo "0"
|
||||
fi
|
@@ -24,7 +24,7 @@ require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
$hardware = !empty(shell_exec("/etc/rc.d/rc.libvirt test"));
|
||||
if (!$hardware) {
|
||||
echo "<p class='notice'>"._('Your hardware does not have Intel VT-x or AMD-V capability').". "._('This is required to create VMs in KVM').". "._('Please disable the VM function').". ";
|
||||
echo "<a href='https://docs.unraid.net/unraid-os/manual/vm-management#determining-hvmiommu-hardware-support' target='_blank'> "._('Click here to see the Unraid Wiki for more information')."</a></p>";
|
||||
echo "<a href='https://docs.unraid.net/go/determining-hvmiommu-hardware-support/' target='_blank'> "._('View the Docs for more information')."</a></p>";
|
||||
}
|
||||
|
||||
function scan($area, $text) {
|
||||
|
@@ -19,7 +19,7 @@ Cond="exec(\"grep -o '^USAGE=.Y' /boot/config/domain.cfg 2>/dev/null\") && is_fi
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
?>
|
||||
<table id="vmstats" class="tablesorter four shift">
|
||||
<thead class='child'><tr><th class="th1">_(Name)_</th><th class="th2">_(Guest CPU)_</th><th>_(Host CPU)_</th><th>_(Memory)_</th><th>_(Disk IO)_</th><th>_(Network IO)_</th></tr></thead>
|
||||
<thead class='child'><tr><th class="th1">_(Name)_</th><th class="th2">_(Guest CPU)_</th><th>_(Host CPU)_</th><th>_(Memory inuse/Current/Maximum)_</th><th>_(Disk IO)_</th><th>_(Network IO)_</th></tr></thead>
|
||||
<tbody id ="vmstatsbody" class='child'>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@@ -113,7 +113,7 @@ if (strpos($strSelectedTemplate,"User-") !== false) {
|
||||
<table>
|
||||
<tr>
|
||||
<td>_(Icon)_:</td>
|
||||
<td>
|
||||
<td class="template_img_parent">
|
||||
<input type="hidden" name="template[icon]" id="template_icon" value="<?=htmlspecialchars($arrLoad['icon'])?>" />
|
||||
<img id="template_img" src="<?=htmlspecialchars($strIconURL)?>" width="48" height="48" title="_(Change Icon)_..."/>
|
||||
<div id="template_img_chooser_outer">
|
||||
@@ -189,13 +189,13 @@ $(function() {
|
||||
});
|
||||
|
||||
$('.advancedview').switchButton({
|
||||
labels_placement: "left",
|
||||
labels_placement: "right",
|
||||
on_label: "_(XML View)_",
|
||||
off_label: "_(Form View)_",
|
||||
checked: isVMXMLMode()
|
||||
});
|
||||
$('.inlineview').switchButton({
|
||||
labels_placement: "left",
|
||||
labels_placement: "right",
|
||||
off_label: "_(Hide inline xml)_",
|
||||
on_label: "_(Show Inline XML)_",
|
||||
checked: isinlineXMLMode()
|
||||
|
@@ -926,9 +926,9 @@
|
||||
}
|
||||
}
|
||||
$audiodevs_used=[];
|
||||
$strSpecialAddressAudio = "" ;
|
||||
if (!empty($audios)) {
|
||||
foreach ($audios as $i => $audio) {
|
||||
$strSpecialAddressAudio = "" ;
|
||||
// Skip duplicate audio devices
|
||||
if (empty($audio['id']) || in_array($audio['id'], $audiodevs_used)) {
|
||||
continue;
|
||||
@@ -956,9 +956,9 @@
|
||||
}
|
||||
|
||||
$pcidevs_used=[];
|
||||
$strSpecialAddressOther = "" ;
|
||||
if (!empty($pcis)) {
|
||||
foreach ($pcis as $i => $pci_id) {
|
||||
$strSpecialAddressOther = "" ;
|
||||
// Skip duplicate other pci devices
|
||||
if (empty($pci_id) || in_array($pci_id, $pcidevs_used)) {
|
||||
continue;
|
||||
@@ -1989,7 +1989,8 @@
|
||||
if (is_file($disk)) unlink($disk);
|
||||
if (is_file($cfg)) unlink($cfg);
|
||||
if (is_file($xml)) unlink($xml);
|
||||
if (is_dir($dir) && $this->is_dir_empty($dir)) rmdir($dir);
|
||||
#if (is_dir($dir) && $this->is_dir_empty($dir)) rmdir($dir);
|
||||
if (is_dir($dir) && $this->is_dir_empty($dir)) my_rmdir($dir);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -2661,8 +2661,8 @@ function get_vm_usage_stats($collectcpustats = true,$collectdiskstats = true,$co
|
||||
# Memory Metrics
|
||||
if ($state == 1 && $collectmemstats) {
|
||||
$currentmem = $data["balloon.current"];
|
||||
$unusedmem = $data["balloon.unused"];
|
||||
$meminuse = $currentmem - $unusedmem;
|
||||
$maximummem = $data["balloon.maximum"];
|
||||
$meminuse = min($data["balloon.rss"],$data["balloon.current"]);
|
||||
} else $currentmem = $meminuse = 0;
|
||||
|
||||
# Disk
|
||||
@@ -2697,7 +2697,8 @@ function get_vm_usage_stats($collectcpustats = true,$collectdiskstats = true,$co
|
||||
"cpuguest" => $cpuGuestPercent,
|
||||
"timestamp" => $timestamp,
|
||||
"mem" => $meminuse,
|
||||
"maxmem" => $currentmem,
|
||||
"curmem" => $currentmem,
|
||||
"maxmem" => $maximummem,
|
||||
"rxrate" => $rxrate,
|
||||
"rxp" => $rx,
|
||||
"txrate" => $txrate,
|
||||
|
@@ -75,9 +75,11 @@ while (true) {
|
||||
if ($vmdata['state'] == 1) {
|
||||
$running++;
|
||||
$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['maxmem']*1024,$unit)."$unit</td><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";
|
||||
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'],$unit)."$unit/s<br>"._("Write").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s</td><td>";
|
||||
$echodata .= _("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s<br>"._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s</td></tr>";
|
||||
}
|
||||
|
@@ -23,14 +23,15 @@ span.advancedview_panel{display:none;line-height:16px;margin-top:1px}
|
||||
.basic{display:none}
|
||||
.advanced{/*Empty placeholder*/}
|
||||
.switch-button-label.off{color:inherit}
|
||||
.template_img_parent{position:relative}
|
||||
#template_img{cursor:pointer}
|
||||
#template_img:hover{opacity:0.5}
|
||||
#template_img:hover i{opacity:1.0}
|
||||
.template_img_chooser_inner{display:inline-block;width:80px;margin-bottom:15px;margin-right:10px;text-align:center;}
|
||||
.template_img_chooser_inner img{width:48px;height:48px}
|
||||
.template_img_chooser_inner p{text-align:center;line-height:8px;}
|
||||
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative}
|
||||
#template_img_chooser div:hover{background-color:#eee;cursor:pointer;}
|
||||
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative;display:grid;grid-template-columns: repeat(6, minmax(0, 1fr));}
|
||||
#template_img_chooser div:hover{color:#ff8c2f;cursor:pointer;}
|
||||
#form_content{display:none}
|
||||
#vmform .four{overflow:hidden}
|
||||
#vmform .four label{float:left;display:table-cell;width:15%;}
|
||||
|
@@ -23,14 +23,15 @@ span.advancedview_panel{display:none;line-height:16px;margin-top:1px}
|
||||
.basic{display:none}
|
||||
.advanced{/*Empty placeholder*/}
|
||||
.switch-button-label.off{color:inherit}
|
||||
.template_img_parent{position:relative}
|
||||
#template_img{cursor:pointer}
|
||||
#template_img:hover{opacity:0.5}
|
||||
#template_img:hover i{opacity:1.0}
|
||||
.template_img_chooser_inner{display:inline-block;width:80px;margin-bottom:15px;margin-right:10px;text-align:center;}
|
||||
.template_img_chooser_inner img{width:48px;height:48px}
|
||||
.template_img_chooser_inner p{text-align:center;line-height:8px;}
|
||||
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative}
|
||||
#template_img_chooser div:hover{background-color:#eee;cursor:pointer;}
|
||||
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative;display:grid;grid-template-columns: repeat(6, minmax(0, 1fr));}
|
||||
#template_img_chooser div:hover{color:#ff8c2f;cursor:pointer;}
|
||||
#form_content{display:none}
|
||||
#vmform .four{overflow:hidden}
|
||||
#vmform .four label{float:left;display:table-cell;width:15%;}
|
||||
|
@@ -1532,7 +1532,6 @@
|
||||
<table>
|
||||
<tr><td></td>
|
||||
<td>_(Select)_  _(Boot Order)_</td></tr></div>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>_(Other PCI Devices)_:</td>
|
||||
<td>
|
||||
@@ -1557,7 +1556,6 @@
|
||||
<label for="pci<?=$i?>">    <input type="checkbox" name="pci[]" id="pci<?=$i?>" value="<?=htmlspecialchars($arrDev['id'])?>" <?=$extra?>/>  
|
||||
<input type="number" size="5" maxlength="5" id="pciboot<?=$i?>" class="narrow pcibootorder" <?=$bootdisable?> style="width: 50px;" name="pciboot[<?=htmlspecialchars($arrDev['id'])?>]" title="_(Boot order)_" value="<?=$pciboot?>" >
|
||||
<?=htmlspecialchars($arrDev['name'])?> | <?=htmlspecialchars($arrDev['type'])?> (<?=htmlspecialchars($arrDev['id'])?>)</label><br/>
|
||||
<td><textarea class="xml" id="xmlpci<?=$i?>" rows=5 disabled ><?=htmlspecialchars($xml2['devices']['other'][$arrDev['id']])?></textarea></td>
|
||||
<?
|
||||
}
|
||||
}
|
||||
@@ -1567,6 +1565,7 @@
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<td><textarea class="xml" id="xmlpci<?=$i?>" rows=2 disabled ><?=htmlspecialchars($xml2['devices']['other']["allotherpci"])?></textarea></td>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
@@ -18,22 +18,18 @@ Nchan="device_list,disk_load,parity_list"
|
||||
<?
|
||||
$keyfile = file_exists(_var($var,'luksKeyfile'));
|
||||
$missing = file_exists('/var/tmp/missing.tmp');
|
||||
$encrypt = false;
|
||||
$spot = _var($var,'mdResyncPos',0)>0;
|
||||
$poolsOnly = (_var($var,'SYS_ARRAY_SLOTS') == 0 ) ? true : false;
|
||||
|
||||
/* only one of $present, $missing, or $wrong will be true, or all will be false */
|
||||
$forced = $present = $wrong = false;
|
||||
foreach ($disks as $disk) {
|
||||
if (!isset($disk['fsType'])) continue;
|
||||
if (strpos(_var($disk,'fsType'),'luks:')!==false || (_var($disk,'fsType')=='auto' && (strpos(_var($var,'defaultFsType'),'luks:')!==false || _var($disk,'luksState',0)==2 || _var($disk,'luksState',0)==3))) {
|
||||
$encrypt = true;
|
||||
if (_var($disk,'luksState',0)==0) $forced = true;
|
||||
if (_var($disk,'luksState',0)==1) $present = true;
|
||||
if (_var($disk,'luksState',0)==2) $missing = true;
|
||||
if (_var($disk,'luksState',0)==3) $wrong = true;
|
||||
}
|
||||
if (strpos(_var($disk,'fsType'),'luks:')!==false || (_var($disk,'fsType')=='auto' && strpos(_var($var,'defaultFsType'),'luks:')!==false)) $forced = true;
|
||||
if (_var($disk,'luksState',0)==1) $present = true;
|
||||
if (_var($disk,'luksState',0)==2) $missing = true;
|
||||
if (_var($disk,'luksState',0)==3) $wrong = true;
|
||||
}
|
||||
$encrypt = $forced || $present || $missing || $wrong;
|
||||
if ($forced && ($present || $missing || $wrong)) $forced = false;
|
||||
|
||||
function check_encryption() {
|
||||
@@ -383,7 +379,7 @@ devices.on('message', function(msg,meta) {
|
||||
$.each(get,function(k,v) {if ($('#line'+k).length>0) $('#line'+k).html(v);});
|
||||
// button control
|
||||
if ($('#pauseButton').length>0 && $('#pauseButton').prop('disabled')==false) {
|
||||
if (!msg && $('#cancelButton').length>0 && $('#cancelButton').val()=="_(Cancel)_") {
|
||||
if ((get === "") && $('#cancelButton').val()=="_(Cancel)_") {
|
||||
$('#cancelButton').val("_(Done)_").prop('onclick',null).off('click').click(function(){refresh();});
|
||||
$('#pauseButton').prop('disabled',true);
|
||||
$('#cancelText').html('');
|
||||
@@ -464,7 +460,7 @@ window.onunload = function(){
|
||||
<? if (_var($var,'fsNumUnmountable',0)>0):?>
|
||||
<tr><td>**<?=_('Unmountable disk'.(_var($var,'fsNumUnmountable',0)==1?'':'s').' present')?>:**<br>
|
||||
<? $cache = [];
|
||||
foreach ($disks as $disk) if (substr(_var($disk,'fsStatus'),0,11)=='Unmountable' || in_array(prefix(_var($disk,'name')),$cache)) {
|
||||
foreach ($disks as $disk) if (substr(_var($disk,'fsStatus'),0,11)=='Unmountable' || in_array(pool_name(_var($disk,'name')),$cache)) {
|
||||
if (strlen(_var($disk,'id'))) echo "<span class='blue-text'>".my_disk(_var($disk,'name'))."</span> • ".my_id(_var($disk,'id'))." ("._var($disk,'device').")<br>";
|
||||
if (in_array(_var($disk,'name'),$pools)) $cache[] = $disk['name'];
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@ $domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
if (!isset($domain_cfg['USAGE'])) $vmusage = "N" ; else $vmusage = $domain_cfg['USAGE'];
|
||||
|
||||
// enable/disable graph elements by making hook script executable or not
|
||||
chmod("$docroot/webGui/system/VM_usage",$libvirtd ? 0755 : 0644);
|
||||
chmod("$docroot/webGui/system/VM",$libvirtd ? 0755 : 0644);
|
||||
chmod("$docroot/webGui/system/ZFS_cache",$zfs ? 0755 : 0644);
|
||||
|
||||
foreach ($disks as $disk) {
|
||||
@@ -1188,6 +1188,7 @@ function SleepNow() {
|
||||
function sortTables() {
|
||||
$('table.dashboard').each(function(){
|
||||
var table = $(this);
|
||||
sanitizeMultiCookie(table.prop('id'), ';', true);
|
||||
var index = $.cookie(table.prop('id'));
|
||||
// sorting list exists
|
||||
if (index != null) {
|
||||
|
@@ -207,6 +207,12 @@ function selectDiskFsWidth() {
|
||||
value: 0,
|
||||
text: "<?=_('no devices')?>"
|
||||
}));
|
||||
} else if (($('#diskFsType').val()||'').indexOf('zfs') == -1) {
|
||||
var label = (num_slots == 1) ? "device" : "devices";
|
||||
$('#diskFsWidthZFS').append($('<option>', {
|
||||
value: num_slots,
|
||||
text: _(sprintf('%s '+label,num_slots))
|
||||
}));
|
||||
} else if ($('#diskFsProfileZFS').val() == '') {
|
||||
var label = (num_slots == 1) ? "device" : "devices";
|
||||
$('#diskFsWidthZFS').append($('<option>', {
|
||||
@@ -250,14 +256,14 @@ function selectDiskFsProfile(init) {
|
||||
if (($('#diskFsType').val()||'').indexOf('auto') != -1) {
|
||||
$('#diskFsProfileBTRFS').prop('disabled',true).hide();
|
||||
$('#diskFsProfileZFS').prop('disabled',true).hide();
|
||||
$('#diskFsWidthZFS').prop('disabled',true).hide();;
|
||||
$('#diskFsWidthZFS').hide();;
|
||||
$('#compression').hide(t);
|
||||
$('#autotrim').hide(t);
|
||||
} else if (($('#diskFsType').val()||'').indexOf('btrfs') != -1) {
|
||||
if (!init) $('#diskFsProfileBTRFS').prop('disabled',false);
|
||||
$('#diskFsProfileBTRFS').show();
|
||||
$('#diskFsProfileZFS').prop('disabled',true).hide();
|
||||
$('#diskFsWidthZFS').prop('disabled',true).hide();
|
||||
$('#diskFsWidthZFS').hide();;
|
||||
$('#compression').show(t);
|
||||
<?if (diskType('Cache')):?>
|
||||
$('#autotrim').show(t);
|
||||
@@ -267,10 +273,13 @@ function selectDiskFsProfile(init) {
|
||||
}
|
||||
<?endif;?>
|
||||
} else if (($('#diskFsType').val()||'').indexOf('zfs') != -1) {
|
||||
var subpool = "<?=isSubpool(_var($disk,'name'))?>";
|
||||
$('#diskFsProfileBTRFS').prop('disabled',true).hide();
|
||||
if (subpool.length) {
|
||||
$('#diskFsType').prop('disabled',true).hide();
|
||||
}
|
||||
if (!init) {
|
||||
$('#diskFsProfileZFS').prop('disabled',false);
|
||||
$('#diskFsWidthZFS').prop('disabled',false);
|
||||
}
|
||||
$('#diskFsProfileZFS').show();
|
||||
$('#diskFsWidthZFS').show();
|
||||
@@ -279,7 +288,6 @@ function selectDiskFsProfile(init) {
|
||||
if (num_slots == 2) $('#diskFsProfileZFS').val('mirror');
|
||||
if (num_slots > 2) $('#diskFsProfileZFS').val('raidz1');
|
||||
}
|
||||
selectDiskFsWidth();
|
||||
$('#compression').show(t);
|
||||
<?if (diskType('Cache')):?>
|
||||
$('#autotrim').show(t);
|
||||
@@ -287,6 +295,8 @@ function selectDiskFsProfile(init) {
|
||||
$('#autotrim').show(t);
|
||||
<?endif;?>
|
||||
}
|
||||
selectDiskFsWidth();
|
||||
$('#diskFsGroups').val(0);
|
||||
}
|
||||
function changeFsType() {
|
||||
var fstype = ($('#diskFsType').val()||'').replace('luks:','');
|
||||
@@ -601,7 +611,7 @@ _(Spinup group(s))_:
|
||||
: <input type="text" name="diskSpinupGroup.<?=_var($disk,'idx',0)?>" maxlength="256" value="<?=_var($disk,'spinupGroup')?>">
|
||||
|
||||
<?endif;?>
|
||||
<?if (diskType('Data') || isPool($tag)):?>
|
||||
<?if (diskType('Data','Parity') || isPool($tag)):?>
|
||||
_(Spin down delay)_:
|
||||
: <select name="diskSpindownDelay.<?=_var($disk,'idx',0)?>">
|
||||
<?=mk_option(_var($disk,'spindownDelay'), "-1", _('Use default'))?>
|
||||
@@ -620,11 +630,13 @@ _(Spin down delay)_:
|
||||
<?=mk_option(_var($disk,'spindownDelay'), "9", "9 "._('hours'))?>
|
||||
</select><span id="smart_selftest" class='orange-text'></span>
|
||||
|
||||
<?endif;?>
|
||||
<?if (diskType('Data') || isPool($tag)):?>
|
||||
<?$fsTypeImmutable = _var($var,'fsState')=="Started" || (isPool($tag) && _var($disk,'state')!="NEW_ARRAY")?>
|
||||
<?if (diskType('Data') || (!isSubpool($name) && _var($disk,'slots',0)==1)):?>
|
||||
_(File system status)_:
|
||||
: <?=_(_var($disk,'fsStatus'))?>
|
||||
|
||||
<?$fsTypeImmutable = (_var($var,'fsState')=="Stopped" && !empty(_var($disk,'uuid'))) || (_var($var,'fsState')=="Started" && _var($disk,'fsType')!='auto')?>
|
||||
<?if (diskType('Data') || (!isSubpool($name) && _var($disk,'slots',0)==1)):?>
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="changeFsType()" <?=disabled_if($fsTypeImmutable)?>>
|
||||
<?=mk_option(_var($disk,'fsType'), "auto", _('auto'))?>
|
||||
@@ -641,6 +653,9 @@ _(File system type)_:
|
||||
:info_file_system_help:
|
||||
|
||||
<?elseif (!isSubpool($name) && _var($disk,'slots',0)>1):?>
|
||||
_(File system status)_:
|
||||
: <?=_(_var($disk,'fsStatus'))?>
|
||||
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsProfile(false)" <?=disabled_if($fsTypeImmutable)?>>
|
||||
<?=mk_option(_var($disk,'fsType'), "auto", _('auto'))?>
|
||||
@@ -649,7 +664,9 @@ _(File system type)_:
|
||||
<?=mk_option(_var($disk,'fsType'), "luks:zfs", _('zfs')." - "._('encrypted'))?>
|
||||
<?=mk_option(_var($disk,'fsType'), "luks:btrfs", _('btrfs')." - "._('encrypted'))?>
|
||||
</select>
|
||||
<select id="diskFsProfileBTRFS" name="diskFsProfile.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
|
||||
_(Allocation profile)_:
|
||||
: <select id="diskFsProfileBTRFS" name="diskFsProfile.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
<?=mk_option(_var($disk,'fsProfile'),"single", _('single'))?>
|
||||
<?if (_var($disk,'slots',0)>=2) echo mk_option(_var($disk,'fsProfile'),"raid0", _('raid0'))?>
|
||||
<?if (_var($disk,'slots',0)>=2) echo mk_option(_var($disk,'fsProfile'),"raid1", _('raid1'))?>
|
||||
@@ -668,10 +685,11 @@ _(File system type)_:
|
||||
<?if (_var($disk,'slots',0)>=4) echo mk_option(_var($disk,'fsProfile'),"raidz3", _('raidz3'))?>
|
||||
</select>
|
||||
<select id="diskFsWidthZFS" name="diskFsWidth.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
<input id="diskFsGroups" name="diskFsGroups.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
</select>
|
||||
<?elseif (isSubpool($name)=="special" || isSubpool($name)=="logs" || isSubpool($name)=="dedup"):?>
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsProfile(false)" <?=disabled_if($fsTypeImmutable)?>>
|
||||
_(Allocation profile)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" disabled>>
|
||||
<?=mk_option(_var($disk,'fsType'), "zfs", _('zfs'))?>
|
||||
</select>
|
||||
<select id="diskFsProfileZFS" name="diskFsProfile.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsWidth()" <?=disabled_if($fsTypeImmutable)?>>
|
||||
@@ -682,8 +700,8 @@ _(File system type)_:
|
||||
<select id="diskFsWidthZFS" name="diskFsWidth.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
</select>
|
||||
<?elseif (isSubpool($name)=="cache"):?>
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsProfile(false)" <?=disabled_if($fsTypeImmutable)?>>
|
||||
_(Allocation profile)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" disabled>>
|
||||
<?=mk_option(_var($disk,'fsType'), "zfs", _('zfs'))?>
|
||||
</select>
|
||||
<select id="diskFsProfileZFS" name="diskFsProfile.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsWidth()" <?=disabled_if($fsTypeImmutable)?>>
|
||||
@@ -693,10 +711,6 @@ _(File system type)_:
|
||||
<select id="diskFsWidthZFS" name="diskFsWidth.<?=_var($disk,'idx',0)?>" style="display:none" <?=disabled_if($fsTypeImmutable)?>>
|
||||
</select>
|
||||
<?elseif (isSubpool($name)=="spares"):?>
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="selectDiskFsProfile(false)" <?=disabled_if($fsTypeImmutable)?>>
|
||||
<?=mk_option(_var($disk,'fsType'), "zfs", _('zfs'))?>
|
||||
</select>
|
||||
<?endif;?>
|
||||
|
||||
<?if (isSubpool($name)===false):?>
|
||||
@@ -757,11 +771,10 @@ _(Critical disk utilization threshold)_ (%):
|
||||
<?endif;?>
|
||||
<?if (isPool($name) && strpos($name,$_tilde_)===false):?>
|
||||
<?if (_var($var,'fsState')=="Stopped" || (_var($var,'fsState')=="Started" && _var($var,'startMode')!="Normal")): $erasable=true; endif;?>
|
||||
<input type="button" id="eraseButton" value="_(Erase)_" onclick="eraseDisk('<?=$name?>')"<?=$erasable?'':' disabled'?>>
|
||||
<input type="button" id="eraseButton" value="_(Erase Pool)_" onclick="eraseDisk('<?=$name?>')"<?=$erasable?'':' disabled'?>>
|
||||
<?endif;?>
|
||||
<?if (_var($var,'fsState')=="Stopped" && isPool($name)):?>
|
||||
<?$empty = _var($disk,'devices',0)==0?>
|
||||
<input type="button" value="_(Delete Pool)_" onclick="deletePool()"<?=$empty?'':' disabled'?>><?if (!$empty):?>_(Unassign **ALL** devices to delete this pool)_<?endif;?>
|
||||
<input type="button" value="_(Delete Pool)_" onclick="deletePool()"<?=isSubpool($name)?' disabled':''?>>
|
||||
<?endif;?>
|
||||
</form>
|
||||
|
||||
|
@@ -88,7 +88,7 @@ _(Select Proxy)_:
|
||||
>
|
||||
> Outgoing connections from the webgui and some system processes will use the specified http proxy. Docker container installs and updates will use the proxy, but the container itself will not, neither will any VMs.
|
||||
>
|
||||
> For a more comprehensive solution you might consider setting up <u><a href='https://docs.unraid.net/unraid-os/manual/security/vpn/#configuring-vpn-tunneled-access-for-system/' target='_blank'>_(VPN tunnel access for System)_</a></u>.
|
||||
> For a more comprehensive solution you might consider setting up <u><a href='https://docs.unraid.net/go/configuring-vpn-tunneled-access-for-system/' target='_blank'>_(VPN tunnel access for System)_</a></u>.
|
||||
:end
|
||||
|
||||
<p><strong>_(Outgoing Proxy)_ 1</strong></p>
|
||||
|
@@ -86,11 +86,11 @@ _(Enter route + gateway + metric)_:
|
||||
<input type="text" name="gateway" class="fixed" value="" list="device" placeholder="_(gateway name or address)_" required>
|
||||
<datalist id="device"><?foreach ($list as $port):?><?echo "<option value='$port'>"?><?endforeach;?></datalist>
|
||||
<input type="text" name="metric" min="1" max="9999" value="" class="trim" placeholder="1"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred))_*
|
||||
|
||||
<input type="hidden" name="task" value="Add Route">
|
||||
:eth_routing_table_help:
|
||||
|
||||
|
||||
: <input type="submit" name="task" value="_(Add Route)_"><input type="button" value="_(Done)_" class="lock" onclick="done()">
|
||||
: <input type="submit" value="_(Add Route)_"><input type="button" value="_(Done)_" class="lock" onclick="done()">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -19,6 +19,8 @@ Cond="(($var['shareSMBEnabled']!='no') && (isset($name)?array_key_exists($name,$
|
||||
require_once "$docroot/webGui/include/InputSecurity.php";
|
||||
|
||||
$width = [123,300];
|
||||
/* Sort user array by keys in natural order */
|
||||
uksort($users, 'strnatcmp');
|
||||
?>
|
||||
:smb_security_help:
|
||||
|
||||
|
@@ -1032,14 +1032,13 @@ tstate['wg0'] = "<?=$check_wg0 ? 'active' : 'passive'?>";
|
||||
|
||||
var statistics = new NchanSubscriber('/sub/wireguard',{subscriber:'websocket'});
|
||||
statistics.on('message', function(data) {
|
||||
var list = [];
|
||||
var rows = data.split('\0');
|
||||
var list = [], n = [];
|
||||
var x = 0; var vtun = '';
|
||||
// get all existing tunnels
|
||||
$('div[id^="block-wg"]').each(function(){list.push($(this).prop('id').split('-')[1]);});
|
||||
// update active tunnels
|
||||
for (var i=0,row; row=rows[i]; i++) {
|
||||
var info = row.split(';');
|
||||
var rows = JSON.parse(data);
|
||||
for (var i=0,info; info=rows[i]; i++) {
|
||||
if (info[0] != vtun) {
|
||||
vtun = info[0];
|
||||
// remove tunnel from inactive list
|
||||
@@ -1281,7 +1280,7 @@ _(Local tunnel address IPv6)_:
|
||||
</div>
|
||||
</div>
|
||||
_(Local endpoint)_:
|
||||
: <span class="input"><input type="text" id="endpoint-wg0" name="Endpoint:0" class="subnet" value="<?=$vpn_wg0?'':_var($wg0,'Endpoint:0')?>" onchange="toLC(this);quickValidate(this);" pattern="<?=$validText?>" title="_(IP address or FQDN)_" placeholder="<?=$vpn_wg0?'(_(not used)_)':preg_replace('/^(.+?\.)[0-9a-zA-Z]+(\.(my)?unraid.net)$/','$1<hash>$2',$public)?>">:
|
||||
: <span class="input"><input type="text" class="width:10%;" id="endpoint-wg0" name="Endpoint:0" class="subnet" value="<?=$vpn_wg0?'':_var($wg0,'Endpoint:0')?>" onchange="toLC(this);quickValidate(this);" pattern="<?=$validText?>" title="_(IP address or FQDN)_" placeholder="<?=$vpn_wg0?'(_(not used)_)':preg_replace('/^(.+?\.)[0-9a-zA-Z]+(\.(my)?unraid.net)$/','$1<hash>$2',$public)?>">:
|
||||
<input type="number" name="gui:ListenPort:0" class="port" min="1" max="65535" value="<?=$vpn_wg0?'':_var($wg0,'ListenPort:0')?>" onchange="if(quickValidate(this)) {portRemark($(document.wg0),'wg0',this.value)}" placeholder="<?=$vpn_wg0?'':_var($netport,'wg0')?>"></span>
|
||||
<span class="remark block" style="display:none">_(Remark)_: _(configure your router with port forwarding of port)_ **<span id="my-port-wg0"><?=_var($wg0,'ListenPort:0')?:_var($netport,'wg0')?></span>/_(UDP)_** _(to)_ **<?=$server?>:<?=_var($wg0,'ListenPort:0')?:_var($netport,'wg0')?>**</span><span class="upnp wg0 block"></span>
|
||||
<input type="hidden" name="ListenPort:0" value=""><dl id="endpoint4-wg0" style="display:none"></dl><dl id="endpoint6-wg0" style="display:none"></dl>
|
||||
@@ -1318,7 +1317,7 @@ _(Local tunnel firewall)_:
|
||||
:wg_local_tunnel_firewall_help:
|
||||
|
||||
_(MTU size)_:
|
||||
: <span class="input"><input type="number" name="MTU:0" class="trim" min="68" max="9198" value="<?=_var($wg0,'MTU:0')?>" onchange="quickValidate(this);" placeholder="(_(automatic)_)">_(bytes)_</span>
|
||||
: <span class="input"><input type="number" name="MTU:0" class="trim" min="68" max="9198" value="<?=_var($wg0,'MTU:0')?>" onchange="quickValidate(this);" placeholder="(_(auto)_)">_(bytes)_</span>
|
||||
|
||||
:wg_mtu_size_help:
|
||||
|
||||
@@ -1362,7 +1361,7 @@ _(Peer type of access)_:
|
||||
<?=mk_option(_var($wg0,"TYPE:$i"), "7", _("VPN tunneled access for system"),count($peer_wg0)==1?'':'disabled')?>
|
||||
<?=mk_option(_var($wg0,"TYPE:$i"), "8", _("VPN tunneled access for docker"),count($peer_wg0)==1?'':'disabled')?>
|
||||
</select></span>
|
||||
<span id="access-type-<?=$i?>" class="access-type"></span>
|
||||
<span id="access-type-<?=$i?>"</span>
|
||||
|
||||
<?if ($i==1):?>
|
||||
> ?>)
|
||||
@@ -1426,8 +1425,8 @@ _(Persistent keepalive)_:
|
||||
:wg_persistent_keepalive_help:
|
||||
|
||||
</div>
|
||||
<span class="pin">_(Data received)_: <span class="rx-wg0-<?=$i?>">0 B</span>_(Data sent)_: <span class="tx-wg0-<?=$i?>">0 B</span><br>_(Last handshake)_: <span class="hs-wg0-<?=$i?>">_(unknown)_</span></span>
|
||||
</div>
|
||||
<span class="pin">_(Data received)_: <span class="rx-wg0-<?=$i?>">0 B</span>_(Data sent)_: <span class="tx-wg0-<?=$i?>">0 B</span><br>_(Last handshake)_: <span class="hs-wg0-<?=$i?>">_(unknown)_</span></span>
|
||||
<?endforeach;?>
|
||||
|
||||
|
||||
|
@@ -224,7 +224,7 @@ _(Local tunnel address IPv6)_:
|
||||
</div>
|
||||
</div>
|
||||
_(Local endpoint)_:
|
||||
: <span class="input"><input type="text" id="endpoint-wgX" name="Endpoint:0" class="subnet" value="<?=$vpn_wgX?'':_var($wgX,'Endpoint:0')?>" onchange="toLC(this);quickValidate(this);" pattern="<?=$validText?>" title="_(IP address or FQDN)_" placeholder="<?=$vpn_wgX?'(_(not used)_)':preg_replace('/^(www\.).+(\.unraid.net)$/','$1<hash>$2',$public)?>">:
|
||||
: <span class="input"><input type="text" class="width:10%;" id="endpoint-wgX" name="Endpoint:0" class="subnet" value="<?=$vpn_wgX?'':_var($wgX,'Endpoint:0')?>" onchange="toLC(this);quickValidate(this);" pattern="<?=$validText?>" title="_(IP address or FQDN)_" placeholder="<?=$vpn_wgX?'(_(not used)_)':preg_replace('/^(www\.).+(\.unraid.net)$/','$1<hash>$2',$public)?>">:
|
||||
<input type="number" name="gui:ListenPort:0" class="port" min="1" max="65535" value="<?=$vpn_wgX?'':_var($wgX,'ListenPort:0')?>" onchange="if(quickValidate(this)) {portRemark($(document.wgX),'wgX',this.value)}" placeholder="<?=$vpn_wgX?'':_var($netport,'wgX')?>"></span>
|
||||
<span class="remark block" style="display:none">_(Remark)_: _(configure your router with port forwarding of port)_ **<span id="my-port-wgX"><?=_var($wgX,'ListenPort:0')?:_var($netport,'wgX')?></span>/_(UDP)_** _(to)_ **<?=$server?>:<?=_var($wgX,'ListenPort:0')?:_var($netport,'wgX')?>**</span><span class="upnp wgX block"></span>
|
||||
<input type="hidden" name="ListenPort:0" value=""><dl id="endpoint4-wgX" style="display:none"></dl><dl id="endpoint6-wgX" style="display:none"></dl>
|
||||
@@ -261,7 +261,7 @@ _(Local tunnel firewall)_:
|
||||
:wg_local_tunnel_firewall_help:
|
||||
|
||||
_(MTU size)_:
|
||||
: <span class="input"><input type="number" name="MTU:0" class="trim" min="68" max="9198" value="<?=_var($wgX,'MTU:0')?>" onchange="quickValidate(this);" placeholder="(_(automatic)_)">_(bytes)_</span>
|
||||
: <span class="input"><input type="number" name="MTU:0" class="trim" min="68" max="9198" value="<?=_var($wgX,'MTU:0')?>" onchange="quickValidate(this);" placeholder="(_(auto)_)">_(bytes)_</span>
|
||||
|
||||
:wg_mtu_size_help:
|
||||
|
||||
@@ -305,7 +305,7 @@ _(Peer type of access)_:
|
||||
<?=mk_option(_var($wgX,"TYPE:$i"), "7", _("VPN tunneled access for system"),count($peer_wgX)==1?'':'disabled')?>
|
||||
<?=mk_option(_var($wgX,"TYPE:$i"), "8", _("VPN tunneled access for docker"))?>
|
||||
</select></span>
|
||||
<span id="access-type-<?=$i?>" class="access-type"></span>
|
||||
<span id="access-type-<?=$i?>"></span>
|
||||
|
||||
<?if ($i==1):?>
|
||||
> ?>)
|
||||
@@ -369,8 +369,8 @@ _(Persistent keepalive)_:
|
||||
:wg_persistent_keepalive_help:
|
||||
|
||||
</div>
|
||||
<span class="pin">_(Data received)_: <span class="rx-wgX-<?=$i?>">0 B</span>_(Data sent)_: <span class="tx-wgX-<?=$i?>">0 B</span><br>_(Last handshake)_: <span class="hs-wgX-<?=$i?>">_(unknown)_</span></span>
|
||||
</div>
|
||||
<span class="pin">_(Data received)_: <span class="rx-wgX-<?=$i?>">0 B</span>_(Data sent)_: <span class="tx-wgX-<?=$i?>">0 B</span><br>_(Last handshake)_: <span class="hs-wgX-<?=$i?>">_(unknown)_</span></span>
|
||||
<?endforeach;?>
|
||||
|
||||
|
||||
|
@@ -37,26 +37,3 @@
|
||||
]]>
|
||||
</Script>
|
||||
</Agent>
|
||||
<Agent>
|
||||
<Name>Pushbullet</Name>
|
||||
<Variables>
|
||||
<Variable Help="The Access Token can be found [a href='https://www.pushbullet.com/account' target='_blank'] [u]here[/u].[/a]" Desc="Access Token" Default="">TOKEN</Variable>
|
||||
<Variable Help="Specify the fields which are included in the title of the notification." Desc="Notification Title" Default="$SUBJECT">TITLE</Variable>
|
||||
<Variable Help="Specify the fields which are included in the message body of the notification." Desc="Notification Message" Default="$DESCRIPTION">MESSAGE</Variable>
|
||||
</Variables>
|
||||
<Script>
|
||||
<![CDATA[
|
||||
#!/bin/bash
|
||||
##########
|
||||
{0}
|
||||
##########
|
||||
MESSAGE=$(echo "$MESSAGE" | sed -e 's:<br[ /]*>:\\n:gI' -e 's/<[^>]*>//g')
|
||||
|
||||
curl -s -k \
|
||||
-X POST --header "Authorization: Bearer $TOKEN" \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d "{\"type\": \"note\", \"title\": \"$TITLE\", \"body\": \"$MESSAGE\"}" \
|
||||
https://api.pushbullet.com/v2/pushes 2>&1
|
||||
]]>
|
||||
</Script>
|
||||
</Agent>
|
||||
|
24
emhttp/plugins/dynamix/agents/Pushbullet.xml
Normal file
24
emhttp/plugins/dynamix/agents/Pushbullet.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Agent>
|
||||
<Name>Pushbullet</Name>
|
||||
<Variables>
|
||||
<Variable Help="The Access Token can be found [a href='https://www.pushbullet.com/account' target='_blank'] [u]here[/u].[/a]" Desc="Access Token" Default="">TOKEN</Variable>
|
||||
<Variable Help="Specify the fields which are included in the title of the notification." Desc="Notification Title" Default="$SUBJECT">TITLE</Variable>
|
||||
<Variable Help="Specify the fields which are included in the message body of the notification." Desc="Notification Message" Default="$DESCRIPTION">MESSAGE</Variable>
|
||||
</Variables>
|
||||
<Script>
|
||||
<![CDATA[
|
||||
#!/bin/bash
|
||||
##########
|
||||
{0}
|
||||
##########
|
||||
MESSAGE=$(echo "$MESSAGE" | sed -e 's:<br[ /]*>:\\n:gI' -e 's/<[^>]*>//g')
|
||||
|
||||
curl -s -k \
|
||||
-X POST --header "Authorization: Bearer $TOKEN" \
|
||||
--header 'Content-Type: application/json' \
|
||||
-d "{\"type\": \"note\", \"title\": \"$TITLE\", \"body\": \"$MESSAGE\"}" \
|
||||
https://api.pushbullet.com/v2/pushes 2>&1
|
||||
]]>
|
||||
</Script>
|
||||
</Agent>
|
@@ -543,7 +543,7 @@ $theme_dark = in_array($display['theme'], ['black', 'gray']);
|
||||
</div>
|
||||
|
||||
<? if (($twoFactorRequired && !empty($token)) || !$twoFactorRequired) { ?>
|
||||
<p class="js-removeTimeout"><a href="https://docs.unraid.net/unraid-os/manual/troubleshooting#lost-root-password" target="_blank"><?=_('Password recovery')?></a></p>
|
||||
<p class="js-removeTimeout"><a href="https://docs.unraid.net/go/lost-root-password/" target="_blank"><?=_('Password recovery')?></a></p>
|
||||
<? } ?>
|
||||
|
||||
</div>
|
||||
|
@@ -582,7 +582,7 @@ function viewHistory() {
|
||||
}
|
||||
function flashReport() {
|
||||
$.post('/webGui/include/Report.php',{cmd:'config'},function(check){
|
||||
if (check>0) addBannerWarning("<?=_('Your flash drive is corrupted or offline').'. '._('Post your diagnostics in the forum for help').'.'?> <a target='_blank' href='https://docs.unraid.net/unraid-os/manual/changing-the-flash-device'><?=_('See also here')?></a>");
|
||||
if (check>0) addBannerWarning("<?=_('Your flash drive is corrupted or offline').'. '._('Post your diagnostics in the forum for help').'.'?> <a target='_blank' href='https://docs.unraid.net/go/changing-the-flash-device/'><?=_('See also here')?></a>");
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
@@ -803,7 +803,7 @@ default:
|
||||
}
|
||||
echo "</span></span><span id='countdown'></span><span id='user-notice' class='red-text'></span>";
|
||||
echo "<span id='copyright'>Unraid® webGui ©2024, Lime Technology, Inc.";
|
||||
echo " <a href='https://docs.unraid.net/category/manual' target='_blank' title=\""._('Online manual')."\"><i class='fa fa-book'></i> "._('manual')."</a>";
|
||||
echo " <a href='https://docs.unraid.net/go/manual/' target='_blank' title=\""._('Online manual')."\"><i class='fa fa-book'></i> "._('manual')."</a>";
|
||||
echo "</span></div>";
|
||||
?>
|
||||
<script>
|
||||
|
@@ -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", "disks", "remotes", "rootshare", "user0"];
|
||||
$excludedFolders = ["RecycleBin", "addons", "remotes", "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>";
|
||||
|
@@ -344,6 +344,28 @@ function my_mkdir($dirname,$permissions = 0777,$recursive = false,$own = "nobody
|
||||
chgrp($dirname, $grp);
|
||||
return($rtncode);
|
||||
}
|
||||
function my_rmdir($dirname) {
|
||||
if (!is_dir($dirname)) return(false);
|
||||
if (strpos($dirname,'/mnt/user/')===0) {
|
||||
$realdisk = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($dirname)." 2>/dev/null"));
|
||||
if (!empty($realdisk)) {
|
||||
$dirname = str_replace('/mnt/user/', "/mnt/$realdisk/", $dirname);
|
||||
}
|
||||
}
|
||||
$fstype = trim(shell_exec(" stat -f -c '%T' $dirname"));
|
||||
$rtncode = false;
|
||||
switch ($fstype) {
|
||||
case "zfs":
|
||||
$zfsdataset = trim(shell_exec("zfs list -H -o name $dirname")) ;
|
||||
$rtncode=exec("zfs destroy \"$zfsdataset\"");
|
||||
break;
|
||||
case "btrfs":
|
||||
default:
|
||||
$rtncode = rmdir($dirname);
|
||||
break;
|
||||
}
|
||||
return($rtncode);
|
||||
}
|
||||
function get_realvolume($path) {
|
||||
if (strpos($path,"/mnt/user/",0) === 0)
|
||||
$reallocation = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($path)." 2>/dev/null"));
|
||||
|
@@ -128,6 +128,9 @@ function no_tilde($name) {
|
||||
function prefix($key) {
|
||||
return preg_replace('/\d+$/','',$key);
|
||||
}
|
||||
function pool_name($key) {
|
||||
return preg_replace('/(\d+$|~.*$)/', '', $key);
|
||||
}
|
||||
function native($name, $full=0) {
|
||||
global $_tilde_, $_arrow_;
|
||||
switch ($full) {
|
||||
|
@@ -119,12 +119,12 @@ function assignment(&$disk) {
|
||||
function vfs_luks($fs) {
|
||||
return str_starts_with($fs,'luks:');
|
||||
}
|
||||
function vfs_type(&$disk, $parent=false) {
|
||||
function vfs_type(&$disk) {
|
||||
global $disks, $pools, $crypto;
|
||||
$fsType = _var($disk,'fsType');
|
||||
$name = _var($disk,'name');
|
||||
$type = ($parent || _var($disk,'type')=='Cache' && !in_array($name,$pools)) ? _var($disks[prefix($name)],'fsType') : $fsType;
|
||||
$fsType = _var($disk,'fsType','');
|
||||
$luks = '';
|
||||
if (empty($fsType))
|
||||
return $fsType;
|
||||
if ($crypto) switch (_var($disk,'luksState',0)) {
|
||||
case 0:
|
||||
if (vfs_luks($fsType))
|
||||
@@ -146,14 +146,14 @@ function vfs_type(&$disk, $parent=false) {
|
||||
$luks = "<a class='info'><i class='padlock fa fa-lock red-text'></i><span>"._('Device locked: unknown error')."</span></a>";
|
||||
break;
|
||||
}
|
||||
return $luks.str_replace('luks:','',$type);
|
||||
return $luks.str_replace('luks:','',$fsType);
|
||||
}
|
||||
function fs_info(&$disk) {
|
||||
global $display, $pools;
|
||||
global $display;
|
||||
$echo = [];
|
||||
if (empty($disk['fsStatus']) || $disk['fsStatus']=='-') {
|
||||
return (_var($disk,'type')=='Cache') ? "<td>".vfs_type($disk,true)."</td><td colspan='3'>"._('Device is part of a pool')."</td>" : "<td colspan='4'></td>";
|
||||
} elseif (_var($disk,'fsStatus')=='Mounted') {
|
||||
if (empty(_var($disk,'fsStatus','')))
|
||||
return "<td colspan='4'></td>";
|
||||
if (_var($disk,'fsStatus')=='Mounted') {
|
||||
$echo[] = "<td>".vfs_type($disk)."</td>";
|
||||
$echo[] = "<td>".my_scale(_var($disk,'fsSize',0)*1024,$unit,-1)." $unit</td>";
|
||||
if ($display['text']%10==0) {
|
||||
@@ -194,7 +194,7 @@ function array_offline(&$disk, $pool='') {
|
||||
if (_var($disk,'type')=='Parity') $warning = $text;
|
||||
} elseif (_var($var,'mdState')=='RECON_DISK') {
|
||||
if (in_array(_var($disk,'status'),$status)) $warning = $text;
|
||||
} elseif (_var($disk['status'])=='DISK_NEW') {
|
||||
} elseif (_var($disk['status'])=='DISK_NEW' && _var($var,'mdResyncAction')=='clear') {
|
||||
$warning = $text;
|
||||
}
|
||||
}
|
||||
@@ -209,7 +209,9 @@ function array_offline(&$disk, $pool='') {
|
||||
case 'DISK_NP_MISSING':
|
||||
$echo[] = "<td>".device_info($disk,false)."<br><span class='diskinfo'><em>"._('Missing')."</em></span></td>";
|
||||
$echo[] = "<td>".assignment($disk)."<em>{$disk['idSb']} - ".my_scale(_var($disk,'sizeSb',0)*1024,$unit)." $unit</em></td>";
|
||||
$echo[] = "<td colspan='8'></td>";
|
||||
$echo[] = "<td colspan='4'></td>";
|
||||
$echo[] = "<td>".vfs_type($disk)."</td>";
|
||||
$echo[] = "<td colspan='3'></td>";
|
||||
break;
|
||||
case 'DISK_NP_DSBL':
|
||||
$echo[] = "<td>".device_info($disk,false)."</td>";
|
||||
@@ -359,8 +361,9 @@ function array_slots() {
|
||||
return implode($echo);
|
||||
}
|
||||
function cache_slots($off,$pool,$min,$slots) {
|
||||
global $var;
|
||||
global $var, $disks;
|
||||
$off = $off && $min ? ' disabled' : '';
|
||||
$off = '';
|
||||
$max = _var($var,'MAX_CACHESZ');
|
||||
$echo = [];
|
||||
$echo[] = "<form method='POST' action='/update.htm' target='progressFrame'>";
|
||||
@@ -368,10 +371,13 @@ function cache_slots($off,$pool,$min,$slots) {
|
||||
$echo[] = "<input type='hidden' name='changeSlots' value='apply'>";
|
||||
$echo[] = "<input type='hidden' name='poolName' value='$pool'>";
|
||||
$echo[] = "<select class='narrow' name='poolSlots' onChange='devices.start();this.form.submit()'{$off}>";
|
||||
if (_var($disks[$pool],'state')=='NEW_ARRAY' || str_contains(_var($diks[$pool],'state'),'NO_DEVICES')) {
|
||||
$option = _('none');
|
||||
$echo[] = "<option value='0'>$option</option>";
|
||||
}
|
||||
for ($n=$min; $n<=$max; $n++) {
|
||||
$option = $n ?: _('none');
|
||||
$selected = ($n==$slots) ? ' selected' : '';
|
||||
$echo[] = "<option value='$n'{$selected}>$option</option>";
|
||||
$echo[] = "<option value='$n'{$selected}>$n</option>";
|
||||
}
|
||||
$echo[] = "</select></form>";
|
||||
return implode($echo);
|
||||
@@ -507,7 +513,6 @@ while (true) {
|
||||
} else {
|
||||
foreach ($Cache as $disk) if (prefix($disk['name'])==$pool) {
|
||||
$fstype = str_replace('luks:','',_var($disk,'fsType'));
|
||||
if (substr(_var($Cache[$pool],'fsStatus'),0,11)=='Unmountable' && empty($disk['fsStatus'])) $disk['fsStatus'] = _var($Cache[$pool],'fsStatus');
|
||||
$echo[$a][] = array_online($disk,$fstype);
|
||||
}
|
||||
if (strcmp($root,$pool)!=0) $Cache[$root]['devices'] += $Cache[$pool]['devices'];
|
||||
|
@@ -107,6 +107,9 @@ while (true) {
|
||||
file_put_contents($log, "$timestamp|$duration|$speed|$status|$error|$action|$size\n", FILE_APPEND);
|
||||
|
||||
delete_file($stamps, $resync);
|
||||
|
||||
/* Parity check is completed. */
|
||||
$echo = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +133,7 @@ while (true) {
|
||||
$process = 2;
|
||||
} elseif (exec('ps -C btrfs -o cmd=|grep -cv show') > 0) {
|
||||
$process = 3;
|
||||
} elseif (exec("zpool status|grep -c 'scrub in progress'") > 0) {
|
||||
} elseif (exec("zpool status 2>/dev/null | grep -c 'scrub in progress'") > 0) {
|
||||
$process = 4;
|
||||
} else {
|
||||
$process = 0;
|
||||
|
@@ -59,7 +59,7 @@ while (true) {
|
||||
exec("sensors -uA 2>/dev/null|grep -Po 'fan\d_input: \K\d+'",$fans);
|
||||
[$total,$free] = $memory;
|
||||
$used = $total-$free;
|
||||
$names = [_('Services'),_('Free')];
|
||||
$names = [_('System'),_('Free')];
|
||||
$bytes = $echo = [];
|
||||
$hooks = array_filter(glob("/usr/local/emhttp/plugins/*/system/*",GLOB_NOSORT),function($file){return is_executable($file);});
|
||||
foreach ($hooks as $hook) {
|
||||
|
@@ -73,11 +73,13 @@ while (true) {
|
||||
if ($vmdata['state'] == 1) {
|
||||
$vmencode = str_replace(" "," ",$vm);
|
||||
$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['maxmem']*1024,$unit)."$unit</span>";
|
||||
$echo[$vmencode ]['disk'] = "<span>Disk: "._("Rd").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s</span>";
|
||||
$echo[$vmencode ]['net'] = "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s</span>";
|
||||
$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";
|
||||
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'],$unit)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s  </span>";
|
||||
$echo[$vmencode ]['net'] = "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s  </span>";
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -113,8 +113,18 @@ function maskIP($file) {
|
||||
// anonymize public IPv4 addresses
|
||||
$rfc1918 = "(127|10|172\.1[6-9]|172\.2[0-9]|172\.3[0-1]|192\.168)((\.[0-9]{1,3}){2,3}([/\" .]|$))";
|
||||
run("sed -ri 's/([\"\[ ]){$rfc1918}/\\1@@@\\2\\3/g; s/([\"\[ ][0-9]{1,3}\.)([0-9]{1,3}\.){2}([0-9]{1,3})([/\" .]|$)/\\1XXX.XXX.\\3\\4/g; s/@@@//g' ".escapeshellarg($file)." 2>/dev/null");
|
||||
|
||||
// anonymize full IPv6 addresses
|
||||
run("sed -ri 's/([\"\[ ]([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})([/\" .]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' ".escapeshellarg($file)." 2>/dev/null");
|
||||
$file_escaped = escapeshellarg($file);
|
||||
|
||||
// Anonymize IPv6 addresses without brackets
|
||||
run("sed -ri 's/(([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' $file_escaped 2>/dev/null");
|
||||
|
||||
// Anonymize IPv6 addresses with brackets
|
||||
run("sed -ri 's/(\[([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})(\])([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' $file_escaped 2>/dev/null");
|
||||
|
||||
// Handle any remaining edge cases, e.g., addresses with subnet masks
|
||||
run("sed -ri 's/(([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})(\/[0-9]{1,3})([ .:/]|$)/\\1XXXX:XXXX:XXXX:\\5\\7/g' $file_escaped 2>/dev/null");
|
||||
}
|
||||
function download_url($url, $path="", $bg=false, $timeout=15) {
|
||||
$ch = curl_init();
|
||||
@@ -469,7 +479,7 @@ if (!$all) {
|
||||
maskIP("/$diag/config/network.cfg");
|
||||
}
|
||||
// include listening interfaces
|
||||
run("$docroot/webGui/scripts/show_interfaces ip|tr -d ' '|tr '#' ' '|tr ',' '\n' >".escapeshellarg("/$diag/config/listen.txt"));
|
||||
run("$docroot/webGui/scripts/show_interfaces ip|tr ',' '\n' >".escapeshellarg("/$diag/config/listen.txt"));
|
||||
run("$docroot/webGui/scripts/error_interfaces|sed 's/<i.*i>//' >>".escapeshellarg("/$diag/config/listen.txt"));
|
||||
if (!$all) maskIP("/$diag/config/listen.txt");
|
||||
|
||||
|
@@ -19,7 +19,7 @@ $proxy_ini = '/usr/local/emhttp/state/proxy.ini';
|
||||
$rnd = rand();
|
||||
|
||||
/* Comments to beginning of the proxy_sh file. */
|
||||
$comments = "#!/bin/bash\n"."# Do not edit. This file is autogenerated by /usr/local/sbin/set_proxy.\n";
|
||||
$comments = "#!/bin/bash\n"."# Do not edit. This file is autogenerated by /usr/local/emhttp/plugins/dynamix/scripts/set_proxy.\n";
|
||||
|
||||
/* Set verbose if command line switch is set. */
|
||||
$verbose = false;
|
||||
|
@@ -7,12 +7,12 @@ CALLER="show"
|
||||
|
||||
# include IP addresses?
|
||||
if check && [[ $1 == ip ]]; then
|
||||
ip=()
|
||||
for net in $bind; do
|
||||
ip+=("$net#[$(show -4 dev $net)#$(show -6 dev $net)]")
|
||||
IP=()
|
||||
for NET in $BIND; do
|
||||
IP+=("$NET [$(echo $(show dev $NET)|xargs)]")
|
||||
done
|
||||
bind=${ip[@]}
|
||||
BIND=${IP[@]}
|
||||
fi
|
||||
|
||||
# return list
|
||||
echo ${bind// /, }
|
||||
echo $BIND
|
||||
|
@@ -19,7 +19,7 @@ extract(parse_plugin_cfg('dynamix',true));
|
||||
// cron operation
|
||||
if ($argc==2 && $argv[1]=='cron') {
|
||||
// trim btrfs, xfs
|
||||
echo shell_exec("fstrim -va 2>/dev/null");
|
||||
xfs_btrfs_trim(false);
|
||||
// trim zfs
|
||||
zfs_trim(false);
|
||||
exit(0);
|
||||
@@ -72,16 +72,24 @@ function zfs_trim($write) {
|
||||
}
|
||||
}
|
||||
|
||||
function xfs_btrfs_trim($write) {
|
||||
exec("findmnt -lnt btrfs,xfs -o target,source|awk '\$2!~\"\\\\[\"{print \$1,\$2}'",$mounts);
|
||||
foreach ($mounts as $mount) {
|
||||
[$target,$source] = explode(' ',$mount);
|
||||
if (is_hdd($source)) continue;
|
||||
if ($write) write("$target: ... <i class='fa fa-spin fa-circle-o-notch'></i>\r");
|
||||
$trim = exec("fstrim -v $target 2>/dev/null");
|
||||
if ($write) {
|
||||
if ($trim) write("$trim on $source\r","\n"); else write("\r");
|
||||
} else {
|
||||
if ($trim) echo("$trim on $source\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
write(_("TRIM operation started")."\n","\n","\n");
|
||||
// trim btrfs, xfs
|
||||
exec("findmnt -lnt btrfs,xfs -o target,source|awk '\$2!~\"\\\\[\"{print \$1,\$2}'",$mounts);
|
||||
foreach ($mounts as $mount) {
|
||||
[$target,$source] = explode(' ',$mount);
|
||||
if (is_hdd($source)) continue;
|
||||
write("$target: ... <i class='fa fa-spin fa-circle-o-notch'></i>\r");
|
||||
$trim = exec("fstrim -v $target 2>/dev/null");
|
||||
if ($trim) write("$trim on $source\r","\n"); else write("\r");
|
||||
}
|
||||
xfs_btrfs_trim(true);
|
||||
// trim zfs
|
||||
zfs_trim(true);
|
||||
write(_("Finished")."\n",'_DONE_','');
|
||||
|
@@ -64,7 +64,7 @@ if (!empty($strLoadedModules)) {
|
||||
// Yah! CPU and motherboard supported and enabled in BIOS
|
||||
$hvm = _('Enabled');
|
||||
} else {
|
||||
$hvm = '<a href="https://docs.unraid.net/unraid-os/manual/vm-management#system-preparation" target="_blank">';
|
||||
$hvm = '<a href="https://docs.unraid.net/go/vm-system-preparation/" target="_blank">';
|
||||
if (strpos($strCPUInfo,'vmx')===false && strpos($strCPUInfo, 'svm')===false) {
|
||||
// CPU doesn't support virtualization
|
||||
$hvm .= _('Not Available');
|
||||
@@ -82,7 +82,7 @@ if (!empty($iommu_groups)) {
|
||||
// Yah! CPU and motherboard supported and enabled in BIOS
|
||||
$iommu = _('Enabled');
|
||||
} else {
|
||||
$iommu = '<a href="https://docs.unraid.net/unraid-os/manual/vm-management#determining-hvmiommu-hardware-support" target="_blank">';
|
||||
$iommu = '<a href="https://docs.unraid.net/go/determining-hvmiommu-hardware-support/" target="_blank">';
|
||||
if (strpos($strCPUInfo,'vmx')===false && strpos($strCPUInfo, 'svm')===false) {
|
||||
// CPU doesn't support virtualization so iommu would be impossible
|
||||
$iommu .= _('Not Available');
|
||||
|
0
emhttp/plugins/dynamix/system/ZFS_cache
Normal file → Executable file
0
emhttp/plugins/dynamix/system/ZFS_cache
Normal file → Executable file
@@ -102,6 +102,7 @@ if (isset($_POST['#command'])) {
|
||||
while (!feof($proc)) {
|
||||
write_log(fgets($proc));
|
||||
}
|
||||
@pclose($proc);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@@ -77,6 +77,9 @@ done
|
||||
# this serves to synchronize this script with USB subsystem
|
||||
abort() {
|
||||
read -p "$1 - press ENTER key to reboot..."
|
||||
if /bin/mountpoint -q /boot; then
|
||||
/bin/umount -v /boot
|
||||
fi
|
||||
/bin/echo
|
||||
/sbin/reboot
|
||||
}
|
||||
@@ -161,6 +164,7 @@ else
|
||||
/sbin/mount -w -v -n -o remount /
|
||||
RETVAL=$?
|
||||
[[ $RETVAL -gt 0 ]] && abort "failed to remount $UNRAIDROOT r/w with return value $RETVAL"
|
||||
[[ ! -f /etc/rc.d/rc.S.cont ]] && abort "unable to boot - you must remove 'root=$UNRAIDROOT' from syslinux.cfg"
|
||||
fi
|
||||
|
||||
# set permissions for non vfat boot on /boot
|
||||
|
@@ -58,14 +58,18 @@ if [[ -f $DOCKER_CFG ]]; then
|
||||
. $DOCKER_CFG
|
||||
fi
|
||||
|
||||
# Set storage driver appropriate for backing filesystem, override user setting
|
||||
BACKINGFS=$(findmnt --output FSTYPE --noheadings $DOCKER_ROOT)
|
||||
if [[ $BACKINGFS == btrfs ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=btrfs"
|
||||
elif [[ $BACKINGFS == xfs ]]; then
|
||||
# set storage driver to overlay2 if config value is found, otherwise fall back to native FS driver
|
||||
if [[ $(awk -F'"' '/^DOCKER_BACKINGFS=/{print $2}' $DOCKER_CFG 2>/dev/null) == overlay2 ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=overlay2"
|
||||
elif [[ $BACKINGFS == zfs ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=zfs"
|
||||
else
|
||||
BACKINGFS=$(findmnt --output FSTYPE --noheadings $DOCKER_ROOT)
|
||||
if [[ $BACKINGFS == btrfs ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=btrfs"
|
||||
elif [[ $BACKINGFS == xfs ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=overlay2"
|
||||
elif [[ $BACKINGFS == zfs ]]; then
|
||||
DOCKER_OPTS="$DOCKER_OPTS --storage-driver=zfs"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Less verbose logging by default
|
||||
@@ -86,6 +90,7 @@ MTU=$(ip link show $PORT | grep -Po 'mtu \K\d+')
|
||||
if [[ -n $(ip -6 route show default dev $PORT) ]]; then
|
||||
DOCKER0='fd17::/64'
|
||||
DOCKER_OPTS="--ipv6 --fixed-cidr-v6=$DOCKER0 $DOCKER_OPTS"
|
||||
IPV6_FORWARD=${IPV6_FORWARD:=accept}
|
||||
# create IPv6 NAT rule for docker0
|
||||
[[ -z $(ip6tables -t nat -S | grep -o "$DOCKER0") ]] && run ip6tables -t nat -A POSTROUTING -s $DOCKER0 ! -o docker0 -j MASQUERADE
|
||||
else
|
||||
@@ -453,6 +458,11 @@ docker_network_start(){
|
||||
fi
|
||||
fi
|
||||
done
|
||||
# create IPv6 forward accept rule
|
||||
if [[ $IPV6_FORWARD == accept ]]; then
|
||||
log "creating forward accept rule for IPv6 network"
|
||||
ip6tables -P FORWARD ACCEPT
|
||||
fi
|
||||
log "Network started."
|
||||
}
|
||||
|
||||
|
@@ -61,6 +61,11 @@ mkdir -p $CONFIG/shares
|
||||
mkdir -p $CONFIG/ssh/root
|
||||
mkdir -p $CONFIG/ssl/certs
|
||||
|
||||
# Set default Docker backingfs type to native for existing installations
|
||||
if [[ -f "/boot/config/docker.cfg" ]]; then
|
||||
grep -q "DOCKER_BACKINGFS=" /boot/config/docker.cfg || echo "DOCKER_BACKINGFS=\"native\"" >> /boot/config/docker.cfg
|
||||
fi
|
||||
|
||||
# upgrade network configuration (if needed) and (re)generates our welcome text
|
||||
if [[ -x /usr/local/sbin/create_network_ini ]]; then
|
||||
/usr/local/sbin/create_network_ini init &>/dev/null &
|
||||
@@ -76,11 +81,6 @@ fi
|
||||
/usr/local/emhttp/webGui/scripts/notify smtp-init
|
||||
/usr/local/emhttp/webGui/scripts/notify cron-init
|
||||
|
||||
# restore favorites
|
||||
if [[ -x /usr/local/emhttp/webGui/scripts/restore_favorites ]]; then
|
||||
/usr/local/emhttp/webGui/scripts/restore_favorites
|
||||
fi
|
||||
|
||||
# start nchan monitoring -> stop all running nchan processes when no subscribers are connected
|
||||
if [[ -x /usr/local/sbin/monitor_nchan ]]; then
|
||||
/usr/local/sbin/monitor_nchan
|
||||
@@ -177,6 +177,11 @@ for LANGUAGE in $CONFIG/plugins/lang-*.xml; do
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
# restore favorites
|
||||
if [[ -x /usr/local/emhttp/webGui/scripts/restore_favorites ]]; then
|
||||
/usr/local/emhttp/webGui/scripts/restore_favorites
|
||||
fi
|
||||
|
||||
# Enable persistent bash history
|
||||
PERSISTENT_BASH_HISTORY=$(grep "persist_bash_history" /boot/config/plugins/dynamix/dynamix.cfg 2>/dev/null | cut -d'=' -f2 | sed 's/"//g')
|
||||
if [[ $PERSISTENT_BASH_HISTORY == 1 ]]; then
|
||||
|
@@ -26,7 +26,7 @@ ntpd_running(){
|
||||
}
|
||||
|
||||
ntpd_build(){
|
||||
cp $CONF- $CONF
|
||||
[[ -f $CONF.orig ]] && cp $CONF.orig $CONF || cp $CONF $CONF.orig
|
||||
echo "# Generated entries follow:" >>$CONF
|
||||
echo "interface ignore wildcard" >>$CONF
|
||||
if check && [[ -n $BIND ]]; then
|
||||
|
58
etc/rc.d/rc.sysstat
Normal file
58
etc/rc.d/rc.sysstat
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# chkconfig: 12345 01 99
|
||||
# description: Reset the system activity logs
|
||||
#
|
||||
# /etc/rc.d/rc.sysstat
|
||||
# (C) 2000-2024 Sebastien Godard (sysstat <at> orange.fr)
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: sysstat
|
||||
# Required-Start:
|
||||
# Required-Stop:
|
||||
# Default-Start: 1 2 3 4 5
|
||||
# Default-Stop: 0 6
|
||||
# Description: Reset the system activity logs
|
||||
# Short-Description: Reset the system activity logs
|
||||
### END INIT INFO
|
||||
#@(#) sysstat-12.7.6 startup script:
|
||||
#@(#) Insert a dummy record in current daily data file.
|
||||
#@(#) This indicates that the counters have restarted from 0.
|
||||
|
||||
# Source functions library
|
||||
[ -r /etc/rc.d/init.d/functions ] && . /etc/rc.d/init.d/functions
|
||||
|
||||
RETVAL=0
|
||||
PIDFILE=/var/run/sysstat.pid
|
||||
[ -z "$UID" ] && UID=`id -u`
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
[ $UID -eq 0 ] || exit 4
|
||||
echo $$ > $PIDFILE || exit 1
|
||||
echo -n "Calling the system activity data collector (sadc)... "
|
||||
/usr/lib64/sa/sa1 --boot
|
||||
[ $? -eq 0 ] || RETVAL=1
|
||||
rm -f $PIDFILE
|
||||
echo
|
||||
;;
|
||||
|
||||
status)
|
||||
[ -f $PIDFILE ] || RETVAL=3
|
||||
;;
|
||||
|
||||
stop)
|
||||
[ $UID -eq 0 ] || exit 4
|
||||
;;
|
||||
|
||||
restart|reload|force-reload|condrestart|try-restart)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: sysstat {start|stop|status|restart|reload|force-reload|condrestart|try-restart}"
|
||||
RETVAL=2
|
||||
esac
|
||||
|
||||
exit ${RETVAL}
|
||||
|
Reference in New Issue
Block a user