mirror of
https://github.com/unraid/webgui.git
synced 2026-05-12 07:10:52 -05:00
Merge pull request #1949 from bergware/master
Date and Time enhancements and other fixes
This commit is contained in:
@@ -4,8 +4,8 @@ Icon="icon-docker"
|
||||
Tag="icon-docker"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -52,12 +52,12 @@ $include = $include6 = $address = $address6 = $gateway = $gateway6 = $unset = $p
|
||||
$wide = false;
|
||||
foreach ($custom as $network) {
|
||||
if (in_array($network,$slaves)) continue;
|
||||
$ip4 = exec("ip -br -4 addr show $network scope global|awk '{print $3}'");
|
||||
$ip6 = exec("ip -br -6 addr show $network scope global|awk '{print $3}'");
|
||||
$gw4 = $ip4 ? exec("ip -4 route show dev $network default|awk '{print $3;exit}'") : '';
|
||||
$gw6 = $ip6 ? exec("ip -6 route show dev $network default|awk '{print $3;exit}'") : '';
|
||||
$route4 = $ip4 ? exec("ip -4 route show dev $network $ip4|awk '{print $1;exit}'") : '';
|
||||
$route6 = $ip6 ? exec("ip -6 route show dev $network|awk '/^".substr($ip6,0,strposX($ip6,':',4))."/{print $1;exit}'") : '';
|
||||
$ip4 = exec("ip -4 -br addr show $network scope global | awk '{print $3;exit}'");
|
||||
$ip6 = exec("ip -6 -br addr show $network scope global -temporary -deprecated | awk '{print $3;exit}'");
|
||||
$gw4 = $ip4 ? exec("ip -4 route show dev $network default | awk '{print $3;exit}'") : '';
|
||||
$gw6 = $ip6 ? exec("ip -6 route show dev $network default | awk '{print $3;exit}'") : '';
|
||||
$route4 = $ip4 ? exec("ip -4 route show dev $network $ip4 | awk '{print $1;exit}'") : '';
|
||||
$route6 = $ip6 ? exec("ip -6 route show dev $network | awk '/^".substr($ip6,0,strposX($ip6,':',4))."/{print $1;exit}'") : '';
|
||||
[$eth,$vlan] = my_explode('.',$network);
|
||||
$eth = str_replace(['bond','br'],'eth',$eth);
|
||||
if (!$vlan) {
|
||||
@@ -392,14 +392,6 @@ _(IPv6 custom network on interface)_ <?=$network?> (_(optional)_):
|
||||
<span id="<?=$docker_dhcp6?>_line" class="<?=$auto6Disabled?>">
|
||||
<span class="ip6">**_(Subnet)_:** <?=$route?></span>
|
||||
<span class="gw6">**_(Gateway)_:** <?=$gateway6[$network]?></span>
|
||||
<input type="checkbox" id="<?=$docker_dhcp6?>_dhcp" onchange="changeDHCP(this.id,6)"<?=$dhcp6?'checked':''?><?=$auto6Disabled?>>
|
||||
**_(DHCP pool)_:**<span id="<?=$docker_dhcp6?>_net" class="net <?=$dhcp6Disabled?>"><?=$net?>:</span>
|
||||
<?
|
||||
echo "<input type=\"text\" id=\"{$docker_dhcp6}_text\" value=\"$net_user\" class=\"pool6\" $dhcp6Disabled>/ ";
|
||||
echo "<select id=\"{$docker_dhcp6}_mask\" class=\"mask\" $dhcp6Disabled>";
|
||||
for ($m=$mask+8; $m<=120; $m+=8) echo mk_option($mask_user,$m,$m);
|
||||
echo "</select><input type=\"hidden\" name=\"$docker_dhcp6\" value=\"\"></span>";
|
||||
?>
|
||||
|
||||
<?endforeach;?>
|
||||
<?if ($include6):?>
|
||||
@@ -421,11 +413,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="<?=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?>>
|
||||
<?for ($m=64; $m<=120; $m+=8) echo mk_option($size6?:72,$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>
|
||||
|
||||
<?endif;?>
|
||||
<?endforeach;?>
|
||||
@@ -528,7 +516,6 @@ if (isset($dockercfg[$docker_dhcp6]) || empty($dockercfg["DOCKER_AUTO_$net"])):?
|
||||
_(IPv6 custom network on interface)_ <?=$network?>:
|
||||
: <span class="gw6">**_(Subnet)_:** <?=$route?></span>
|
||||
<span class="gw6">**_(Gateway)_:** <?=$gateway6[$network]?></span>
|
||||
**_(DHCP pool)_:** <?=_var($dockercfg,$docker_dhcp6) ?: "_(not set)_"?>
|
||||
|
||||
<?endif;?>
|
||||
<?endforeach;?>
|
||||
@@ -551,7 +538,7 @@ if (!$vlan) {
|
||||
_(IPv6 custom network on interface)_ <?=$network?>:
|
||||
: <span class="gw6">**_(Subnet)_:** <?=$subnet6?>/<?=$mask6?></span>
|
||||
<span class="gw6">**_(Gateway)_:** <?=_var($dockercfg,"DOCKER_GATEWAY6_$port")?></span>
|
||||
**_(DHCP pool)_:** <?=$range6 ? "$range6/$size6" : "_(not set)_"?>
|
||||
|
||||
<?endif;?>
|
||||
<?endforeach;?>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -13,8 +13,8 @@
|
||||
?>
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/Helpers.php";
|
||||
|
||||
// add translations
|
||||
if (_var($_SERVER,'REQUEST_URI')!='docker' && substr(_var($_SERVER,'REQUEST_URI'),0,7)!='/Docker') {
|
||||
@@ -35,20 +35,10 @@ $dockerManPaths = [
|
||||
'webui-info' => "$docroot/state/plugins/dynamix.docker.manager/docker.json"
|
||||
];
|
||||
|
||||
// load network variables if needed.
|
||||
$ethX = 'eth0';
|
||||
if (!isset($$ethX)) extract(parse_ini_file("$docroot/state/network.ini",true));
|
||||
$host = ipaddr($ethX);
|
||||
|
||||
// get network drivers
|
||||
$driver = DockerUtil::driver();
|
||||
|
||||
// determine active port name
|
||||
$port = file_exists('/sys/class/net/br0') ? 'BR0' : (file_exists('/sys/class/net/bond0') ? 'BOND0' : 'ETH0');
|
||||
|
||||
// Docker configuration file - guaranteed to exist
|
||||
$docker_cfgfile = '/boot/config/docker.cfg';
|
||||
if (file_exists($docker_cfgfile)) {
|
||||
$port = strtoupper(DockerUtil::port());
|
||||
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
|
||||
@@ -277,9 +267,8 @@ class DockerTemplates {
|
||||
}
|
||||
|
||||
private function getControlURL(&$ct, $myIP, $WebUI) {
|
||||
global $host;
|
||||
$port = &$ct['Ports'][0];
|
||||
$myIP = $myIP ?: $this->getTemplateValue($ct['Image'],'MyIP') ?: (_var($ct,'NetworkMode')=='host'||_var($port,'NAT') ? $host : (_var($port,'IP') ?: DockerUtil::myIP($ct['Name'])));
|
||||
$myIP = $myIP ?: $this->getTemplateValue($ct['Image'],'MyIP') ?: (_var($ct,'NetworkMode')=='host'||_var($port,'NAT') ? DockerUtil::host() : (_var($port,'IP') ?: DockerUtil::myIP($ct['Name'])));
|
||||
// Get the WebUI address from the templates as a fallback
|
||||
$WebUI = preg_replace("%\[IP\]%", $myIP, $WebUI ?? $this->getTemplateValue($ct['Image'], 'WebUI'));
|
||||
if (preg_match("%\[PORT:(\d+)\]%", $WebUI, $matches)) {
|
||||
@@ -303,9 +292,11 @@ class DockerTemplates {
|
||||
}
|
||||
|
||||
public function getAllInfo($reload=false,$com=true,$communityApplications=false) {
|
||||
global $driver, $dockerManPaths, $host;
|
||||
global $dockerManPaths;
|
||||
$DockerClient = new DockerClient();
|
||||
$DockerUpdate = new DockerUpdate();
|
||||
$driver = DockerUtil::driver();
|
||||
$host = DockerUtil::host();
|
||||
//$DockerUpdate->verbose = $this->verbose;
|
||||
$info = DockerUtil::loadJSON($dockerManPaths['webui-info']);
|
||||
$autoStart = array_map('var_split', @file($dockerManPaths['autostart-file'],FILE_IGNORE_NEW_LINES) ?: []);
|
||||
@@ -957,7 +948,8 @@ class DockerClient {
|
||||
}
|
||||
|
||||
public function getDockerContainers() {
|
||||
global $driver, $host;
|
||||
$driver = DockerUtil::driver();
|
||||
$host = DockerUtil::host();
|
||||
// Return cached values
|
||||
if (is_array($this::$containersCache)) return $this::$containersCache;
|
||||
$this::$containersCache = [];
|
||||
@@ -1158,7 +1150,7 @@ class DockerUtil {
|
||||
}
|
||||
|
||||
public static function custom() {
|
||||
return static::docker("network ls --filter driver='bridge' --filter driver='macvlan' --filter driver='ipvlan' --format='{{.Name}}' 2>/dev/null|grep -v '^bridge$'",true);
|
||||
return static::docker("network ls --filter driver='bridge' --filter driver='macvlan' --filter driver='ipvlan' --format='{{.Name}}' 2>/dev/null | grep -v '^bridge$'",true);
|
||||
}
|
||||
|
||||
public static function network($custom) {
|
||||
@@ -1168,11 +1160,27 @@ class DockerUtil {
|
||||
}
|
||||
|
||||
public static function cpus() {
|
||||
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
|
||||
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list | sort -nu', $cpus);
|
||||
return $cpus;
|
||||
}
|
||||
|
||||
public static function ctMap($ct, $type='Name') {
|
||||
return static::docker("inspect --format='{{.$type}}' $ct");
|
||||
}
|
||||
|
||||
public static function port() {
|
||||
if (lan_port('br0')) return 'br0';
|
||||
if (lan_port('bond0')) return 'bond0';
|
||||
if (lan_port('eth0')) return 'eth0';
|
||||
if (lan_port('wlan0')) return 'wlan0';
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function host() {
|
||||
$port = static::port();
|
||||
if (!$port) return '';
|
||||
$port = lan_port($port,true)==0 && lan_port('wlan0') ? 'wlan0' : $port;
|
||||
return exec("ip -br -4 addr show $port scope global | sed -r 's/\/[0-9]+//g' | awk '{print $3;exit}'");
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -40,6 +40,9 @@ if (file_exists($user_prefs)) {
|
||||
unset($sort);
|
||||
}
|
||||
|
||||
// get host interface IP address
|
||||
$host = DockerUtil::host();
|
||||
|
||||
// Read container info
|
||||
$allInfo = $DockerTemplates->getAllInfo();
|
||||
$docker = [];
|
||||
@@ -65,12 +68,12 @@ function tailscale_json_dl($file, $url) {
|
||||
mkdir('/tmp/tailscale', 0777, true);
|
||||
}
|
||||
if (!file_exists($file)) {
|
||||
exec("wget -T 3 -q -O " . $file . " " . $url, $output, $dl_status);
|
||||
exec("wget -T 3 -q -O ".$file." ".$url, $output, $dl_status);
|
||||
} else {
|
||||
$fileage = time() - filemtime($file);
|
||||
if ($fileage > 86400) {
|
||||
unlink($file);
|
||||
exec("wget -T 3 -q -O " . $file . " " . $url, $output, $dl_status);
|
||||
exec("wget -T 3 -q -O ".$file." ".$url, $output, $dl_status);
|
||||
}
|
||||
}
|
||||
if ($dl_status === 0) {
|
||||
@@ -144,23 +147,25 @@ foreach ($containers as $ct) {
|
||||
$ports_internal = [];
|
||||
$ports_external = [];
|
||||
if (isset($ct['Ports']['vlan'])) {
|
||||
foreach ($ct['Ports']['vlan'] as $i)
|
||||
foreach ($ct['Ports']['vlan'] as $i) {
|
||||
$ports_external[] = sprintf('%s', $i);
|
||||
}
|
||||
$ports_internal[0] = sprintf('%s', 'all');
|
||||
}
|
||||
foreach($ct['Networks'] as $netName => $netVals) {
|
||||
$networks[] = $netName;
|
||||
$network_ips[] = $running ? $netVals['IPAddress'] : null;
|
||||
|
||||
if (isset($ct['Networks']['host'])) {
|
||||
$ports_external[] = sprintf('%s', $netVals['IPAddress']);
|
||||
$ports_internal[0] = sprintf('%s', 'all');
|
||||
} else if (!isset($ct['Ports']['vlan']) || strpos($ct['NetworkMode'], 'container:') != 0) {
|
||||
} elseif (!isset($ct['Ports']['vlan']) || strpos($ct['NetworkMode'],'container:')!==false) {
|
||||
foreach ($ct['Ports'] as $port) {
|
||||
if (_var($port,'PublicPort') && _var($port,'Driver') == 'bridge')
|
||||
if (_var($port,'PublicPort') && _var($port,'Driver') == 'bridge') {
|
||||
$ports_external[] = sprintf('%s:%s', $host, strtoupper(_var($port,'PublicPort')));
|
||||
if ((!isset($ct['Networks']['host'])) || (!isset($ct['Networks']['vlan'])))
|
||||
}
|
||||
if ((!isset($ct['Networks']['host'])) || (!isset($ct['Networks']['vlan']))) {
|
||||
$ports_internal[] = sprintf('%s:%s', _var($port,'PrivatePort'), strtoupper(_var($port,'Type')));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,7 +181,7 @@ foreach ($containers as $ct) {
|
||||
} else {
|
||||
$appname = htmlspecialchars($name);
|
||||
}
|
||||
echo "<span class='outer'><span id='$id' $menu class='hand'>$image</span><span class='inner'><span class='appname $update'>$appname</span><br><i id='load-$id' class='fa fa-$shape $status $color'></i><span class='state'>"._($status).(!empty($composestack) ? '<br/>Compose Stack: ' . $composestack : '')."</span></span></span>";
|
||||
echo "<span class='outer'><span id='$id' $menu class='hand'>$image</span><span class='inner'><span class='appname $update'>$appname</span><br><i id='load-$id' class='fa fa-$shape $status $color'></i><span class='state'>"._($status).(!empty($composestack) ? '<br/>Compose Stack: '.$composestack : '')."</span></span></span>";
|
||||
echo "<div class='advanced' style='margin-top:8px'>"._('Container ID').": $id<br>";
|
||||
if ($ct['BaseImage']) echo "<i class='fa fa-cubes' style='margin-right:5px'></i>".htmlspecialchars($ct['BaseImage'])."<br>";
|
||||
echo _('By').": ";
|
||||
@@ -240,27 +245,27 @@ foreach ($containers as $ct) {
|
||||
// Construct TSinfo from TSstats
|
||||
$TSinfo = '';
|
||||
if (!$TSstats["Self"]["Online"]) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Online:")."</span><span class='ui-tailscale-value'>❌<br/>"._("Please check the logs!")."</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Online").":</span><span class='ui-tailscale-value'>❌<br/>"._("Please check the logs")."!</span></div>";
|
||||
} else {
|
||||
$TS_version = explode('-', $TSstats["Version"])[0];
|
||||
if (!empty($TS_version)) {
|
||||
if (!empty($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>";
|
||||
$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>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Tailscale").":</span><span class='ui-tailscale-value'>v".$TS_version."</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>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>".("Tailscale").":</span><span class='ui-tailscale-value'>v".$TS_version."</span></div>";
|
||||
}
|
||||
}
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Online:")."</span><span class='ui-tailscale-value'>✅</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Online").":</span><span class='ui-tailscale-value'>✅</span></div>";
|
||||
$TS_DNSName = $TSstats["Self"]["DNSName"];
|
||||
$TS_HostNameActual = substr($TS_DNSName, 0, strpos($TS_DNSName, '.'));
|
||||
if (strcasecmp($TS_HostNameActual, $TShostname) !== 0 && !empty($TS_DNSName)) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Hostname:")."</span><span class='ui-tailscale-value'>"._("Real Hostname")." ➔ " . $TS_HostNameActual . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Hostname").":</span><span class='ui-tailscale-value'>"._("Real Hostname")." ➔ ".$TS_HostNameActual."</span></div>";
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Hostname:")."</span><span class='ui-tailscale-value'>" . $TShostname . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Hostname").":</span><span class='ui-tailscale-value'>".$TShostname."</span></div>";
|
||||
}
|
||||
// Map region relay code to cleartext region if TS_derp_list is available
|
||||
if (!empty($TS_derp_list)) {
|
||||
@@ -271,31 +276,31 @@ foreach ($containers as $ct) {
|
||||
}
|
||||
}
|
||||
if (!empty($TSregion)) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay:")."</span><span class='ui-tailscale-value'>" . $TSregion . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay").":</span><span class='ui-tailscale-value'>".$TSregion."</span></div>";
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay:")."</span><span class='ui-tailscale-value'>" . $TSstats["Self"]["Relay"] . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay").":</span><span class='ui-tailscale-value'>".$TSstats["Self"]["Relay"]."</span></div>";
|
||||
}
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay").":</span><span class='ui-tailscale-value'>" . $TSstats["Self"]["Relay"] . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("DERP Relay").":</span><span class='ui-tailscale-value'>".$TSstats["Self"]["Relay"]."</span></div>";
|
||||
}
|
||||
if (!empty($TSstats["Self"]["TailscaleIPs"])) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Addresses:")."</span><span class='ui-tailscale-value'>" . implode("<br/>", $TSstats["Self"]["TailscaleIPs"]) . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Addresses").":</span><span class='ui-tailscale-value'>".implode("<br/>", $TSstats["Self"]["TailscaleIPs"])."</span></div>";
|
||||
}
|
||||
if (!empty($TSstats["Self"]["PrimaryRoutes"])) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Routes:")."</span><span class='ui-tailscale-value'>" . implode("<br/>", $TSstats["Self"]["PrimaryRoutes"]) . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Routes").":</span><span class='ui-tailscale-value'>".implode("<br/>", $TSstats["Self"]["PrimaryRoutes"])."</span></div>";
|
||||
}
|
||||
if ($TSstats["Self"]["ExitNodeOption"]) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Is Exit Node:")."</span><span class='ui-tailscale-value'>✅</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Is Exit Node").":</span><span class='ui-tailscale-value'>✅</span></div>";
|
||||
} else {
|
||||
if (!empty($TSstats["ExitNodeStatus"])) {
|
||||
$TS_exit_node_status = ($TSstats["ExitNodeStatus"]["Online"]) ? "✅" : "❌";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Exit Node:")."</span><span class='ui-tailscale-value'>" . strstr($TSstats["ExitNodeStatus"]["TailscaleIPs"][0], '/', true) . " | Status: " . $TS_exit_node_status ."</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Exit Node").":</span><span class='ui-tailscale-value'>".strstr($TSstats["ExitNodeStatus"]["TailscaleIPs"][0], '/', true)." | Status: ".$TS_exit_node_status ."</span></div>";
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Is Exit Node:")."</span><span class='ui-tailscale-value'>❌</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Is Exit Node").":</span><span class='ui-tailscale-value'>❌</span></div>";
|
||||
}
|
||||
}
|
||||
if (!empty($TSwebGui)) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("URL:")."</span><span class='ui-tailscale-value'>" . $TSwebGui . "</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("URL").":</span><span class='ui-tailscale-value'>".$TSwebGui."</span></div>";
|
||||
}
|
||||
if (!empty($TSstats["Self"]["KeyExpiry"])) {
|
||||
$TS_expiry = new DateTime($TSstats["Self"]["KeyExpiry"]);
|
||||
@@ -303,17 +308,17 @@ foreach ($containers as $ct) {
|
||||
$TS_expiry_formatted = $TS_expiry->format('Y-m-d');
|
||||
$TS_expiry_diff = $current_Date->diff($TS_expiry);
|
||||
if ($TS_expiry_diff->invert) {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Key Expiry:")."</span><span class='ui-tailscale-value'>❌ "._("Expired! Renew/Disable key expiry!")."</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Key Expiry").":</span><span class='ui-tailscale-value'>❌ "._("Expired! Renew/Disable key expiry!")."</span></div>";
|
||||
} else {
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Key Expiry:")."</span><span class='ui-tailscale-value'>" . $TS_expiry_formatted . " (" . $TS_expiry_diff->days . " days)</span></div>";
|
||||
$TSinfo .= "<div class='ui-tailscale-row'><span class='ui-tailscale-label'>"._("Key Expiry").":</span><span class='ui-tailscale-value'>".$TS_expiry_formatted." (".$TS_expiry_diff->days." days)</span></div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
// Display TSinfo if data was fetched correctly
|
||||
$TS_status = "<br/><div class='TS_tooltip' style='cursor:pointer; display: inline-block;' data-tstitle='" . htmlspecialchars($TSinfo) . "'><img src='/plugins/dynamix.docker.manager/images/tailscale.png' style='height: 1.23em;'> Tailscale</div>";
|
||||
$TS_status = "<br/><div class='TS_tooltip' style='cursor:pointer; display: inline-block;' data-tstitle='".htmlspecialchars($TSinfo)."'><img src='/plugins/dynamix.docker.manager/images/tailscale.png' style='height: 1.23em;'> Tailscale</div>";
|
||||
} else {
|
||||
// Display message to refresh page if Tailscale in the container wasn't maybe ready to get the data
|
||||
$TS_status = "<br/><div class='TS_tooltip' style='display: inline-block;' data-tstitle='"._("Error gathering Tailscale information from container.")."<br/>"._("Please check the logs and refresh the page.")."'><img src='/plugins/dynamix.docker.manager/images/tailscale.png' style='height: 1.23em;'> Tailscale</div>";
|
||||
$TS_status = "<br/><div class='TS_tooltip' style='display: inline-block;' data-tstitle='"._("Error gathering Tailscale information from container").".<br/>"._("Please check the logs and refresh the page")."'><img src='/plugins/dynamix.docker.manager/images/tailscale.png' style='height: 1.23em;'> Tailscale</div>";
|
||||
}
|
||||
} else {
|
||||
// Display message that container isn't running
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -661,8 +661,8 @@ function setXmlVal(&$xml, $value, $el, $attr=null, $pos=0) {
|
||||
}
|
||||
|
||||
function getAllocations() {
|
||||
global $DockerClient, $host;
|
||||
|
||||
global $DockerClient;
|
||||
$host = DockerUtil::host();
|
||||
$ports = [];
|
||||
foreach ($DockerClient->getDockerContainers() as $ct) {
|
||||
$list = $port = [];
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ACTIVE_CONTAINERS="$(docker ps -q --no-trunc 2>/dev/null)"
|
||||
|
||||
# Exit if no containers are active and return zero
|
||||
if [ -z "${ACTIVE_CONTAINERS}" ]; then
|
||||
if [[ -z $ACTIVE_CONTAINERS ]]; then
|
||||
echo "0"
|
||||
exit
|
||||
fi
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
if (is_file($templateslocation)){
|
||||
$arrAllTemplates["User-templates"] = "";
|
||||
$ut = json_decode(file_get_contents($templateslocation),true) ;
|
||||
$ut = json_decode(file_get_contents($templateslocation),true);
|
||||
$arrAllTemplates = array_merge($arrAllTemplates, $ut);
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
$protocol = $lv->domain_get_vmrc_protocol($dom);
|
||||
$reply = ['success' => true];
|
||||
if ($vmrcport > 0) {
|
||||
$reply['vmrcurl'] = autov('/plugins/dynamix.vm.manager/'.$protocol.'.html',true).'&autoconnect=true&host=' . $_SERVER['HTTP_HOST'] ;
|
||||
$reply['vmrcurl'] = autov('/plugins/dynamix.vm.manager/'.$protocol.'.html',true).'&autoconnect=true&host=' . $_SERVER['HTTP_HOST'];
|
||||
if ($protocol == "spice") $reply['vmrcurl'] .= '&port=/wsproxy/'.$vmrcport.'/'; else $reply['vmrcurl'] .= '&port=&path=/wsproxy/' . $wsport . '/';
|
||||
}
|
||||
} else {
|
||||
@@ -185,9 +185,9 @@
|
||||
|
||||
// hot-attach any new usb devices
|
||||
foreach ($arrNewUSBIDs as $strNewUSBID) {
|
||||
if (strpos($strNewUSBID,"#remove")) continue ;
|
||||
$remove = explode('#', $strNewUSBID) ;
|
||||
$strNewUSBID2 = $remove[0] ;
|
||||
if (strpos($strNewUSBID,"#remove")) continue;
|
||||
$remove = explode('#', $strNewUSBID);
|
||||
$strNewUSBID2 = $remove[0];
|
||||
foreach ($arrExistingConfig['usb'] as $arrExistingUSB) {
|
||||
if ($strNewUSBID2 == $arrExistingUSB['id']) continue 2;
|
||||
}
|
||||
@@ -240,7 +240,7 @@
|
||||
// XML view
|
||||
$xml = $_POST['xmldesc'];
|
||||
$arrExistingConfig = custom::createArray('domain',$xml);
|
||||
$newuuid = $arrExistingConfig['uuid'] ;
|
||||
$newuuid = $arrExistingConfig['uuid'];
|
||||
$xml = str_replace($olduuid,$newuuid,$xml);
|
||||
} else {
|
||||
// form view
|
||||
@@ -250,7 +250,7 @@
|
||||
array_update_recursive($arrExistingConfig, $arrUpdatedConfig);
|
||||
$arrConfig = array_replace_recursive($arrExistingConfig, $arrUpdatedConfig);
|
||||
$xml = custom::createXML('domain',$arrConfig)->saveXML();
|
||||
$xml = $lv->appendqemucmdline($xml,$_POST["qemucmdline"]) ;
|
||||
$xml = $lv->appendqemucmdline($xml,$_POST["qemucmdline"]);
|
||||
} else {
|
||||
echo json_encode(['error' => $error]);
|
||||
exit;
|
||||
@@ -283,24 +283,24 @@
|
||||
$strXML = $lv->domain_get_xml($dom);
|
||||
$boolNew = false;
|
||||
$arrConfig = array_replace_recursive($arrConfigDefaults, domain_to_config($uuid));
|
||||
$arrVMUSBs = getVMUSBs($strXML) ;
|
||||
$arrVMUSBs = getVMUSBs($strXML);
|
||||
} else {
|
||||
// edit new VM
|
||||
$boolRunning = false;
|
||||
$strXML = '';
|
||||
$boolNew = true;
|
||||
$arrConfig = $arrConfigDefaults;
|
||||
$arrVMUSBs = getVMUSBs($strXML) ;
|
||||
$arrVMUSBs = getVMUSBs($strXML);
|
||||
}
|
||||
// Add any custom metadata field defaults (e.g. os)
|
||||
if (!$arrConfig['template']['os']) {
|
||||
$arrConfig['template']['os'] = ($arrConfig['domain']['clock']=='localtime' ? 'windows' : 'linux');
|
||||
}
|
||||
$os_type = ((empty($arrConfig['template']['os']) || stripos($arrConfig['template']['os'], 'windows') === false) ? 'other' : 'windows');
|
||||
if (isset($arrConfig['clocks'])) $arrClocks = json_decode($arrConfig['clocks'],true) ; else {
|
||||
if (isset($arrConfig['clocks'])) $arrClocks = json_decode($arrConfig['clocks'],true); else {
|
||||
if ($os_type == "windows") {
|
||||
if ($arrConfig['domain']['hyperv'] == 1) $arrClocks = $arrDefaultClocks['hyperv'] ; else $arrClocks = $arrDefaultClocks['windows'] ;
|
||||
} else $arrClocks = $arrDefaultClocks['other'] ;
|
||||
if ($arrConfig['domain']['hyperv'] == 1) $arrClocks = $arrDefaultClocks['hyperv']; else $arrClocks = $arrDefaultClocks['windows'];
|
||||
} else $arrClocks = $arrDefaultClocks['other'];
|
||||
}
|
||||
|
||||
if (strpos($arrConfig['template']['name'],"User-") !== false) {
|
||||
@@ -356,7 +356,7 @@
|
||||
<?
|
||||
$default_storage=htmlspecialchars($arrConfig['template']['storage']);
|
||||
echo mk_option($default_storage, 'default', _('Default'));
|
||||
|
||||
|
||||
$strShareUserLocalInclude = '';
|
||||
$strShareUserLocalExclude = '';
|
||||
$strShareUserLocalUseCache = 'no';
|
||||
@@ -396,7 +396,7 @@
|
||||
$strLabel = _(my_disk($name),3).' - '.my_scale($disk['fsFree']*1024, $strUnit).' '.$strUnit.' '._('free');
|
||||
echo mk_option($default_storage, $name, $strLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
</td></tr>
|
||||
</table>
|
||||
@@ -407,10 +407,9 @@
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<?
|
||||
$migratehidden = "disabled hidden" ;
|
||||
if ($arrConfig['domain']['cpumode'] == 'host-passthrough') $migratehidden = "" ;
|
||||
$migratehidden = "disabled hidden";
|
||||
if ($arrConfig['domain']['cpumode'] == 'host-passthrough') $migratehidden = "";
|
||||
?>
|
||||
|
||||
<table>
|
||||
@@ -425,7 +424,7 @@
|
||||
<select name="domain[cpumigrate]" id="domain_cpumigrate" <?=$migratehidden?> class="narrow" title="_(define if migratable)_">
|
||||
<?
|
||||
echo mk_option($arrConfig['domain']['cpumigrate'], 'on', 'On');
|
||||
echo mk_option($arrConfig['domain']['cpumigrate'], 'off', 'Off') ;
|
||||
echo mk_option($arrConfig['domain']['cpumigrate'], 'off', 'Off');
|
||||
?>
|
||||
</select>
|
||||
</td>
|
||||
@@ -493,8 +492,8 @@
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
|
||||
<span class="advanced">_(Max)_ _(Memory)_:</span>
|
||||
|
||||
<span class="advanced">_(Max)_ _(Memory)_:</span>
|
||||
<select name="domain[maxmem]" id="domain_maxmem" class="narrow" title="_(define the maximum amount of memory)_">
|
||||
<?
|
||||
echo mk_option($arrConfig['domain']['maxmem'], 128 * 1024, '128 MB');
|
||||
@@ -525,7 +524,7 @@
|
||||
$arrConfig['domain']['machine'] = ValidateMachineType($arrConfig['domain']['machine']);
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
<table>
|
||||
<tr class="advanced">
|
||||
<td>_(Machine)_:</td>
|
||||
@@ -567,8 +566,8 @@
|
||||
</select>
|
||||
|
||||
<?
|
||||
$usbboothidden = "hidden" ;
|
||||
if ($arrConfig['domain']['ovmf'] != '0') $usbboothidden = "" ;
|
||||
$usbboothidden = "hidden";
|
||||
if ($arrConfig['domain']['ovmf'] != '0') $usbboothidden = "";
|
||||
?>
|
||||
<span id="USBBoottext" class="advanced" <?=$usbboothidden?>>_(Enable USB boot)_:</span>
|
||||
|
||||
@@ -778,9 +777,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo mk_option($default_option, 'manual', _('Manual'));
|
||||
?>
|
||||
</select><input type="text" name="disk[<?=$i?>][new]" autocomplete="off" spellcheck="false" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="img,qcow,qcow2" data-pickmatch="^[^.].*" data-pickroot="/mnt/" class="disk" id="disk_<?=$i?>" value="<?=htmlspecialchars($arrDisk['new'])?>" placeholder="_(Separate sub-folder and image will be created based on Name)_"><div class="disk_preview"></div>
|
||||
@@ -932,9 +929,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo mk_option('', 'manual', _('Manual'));
|
||||
?>
|
||||
</select><input type="text" name="disk[{{INDEX}}][new]" autocomplete="off" spellcheck="false" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="img,qcow,qcow2" data-pickmatch="^[^.].*" data-pickroot="/mnt/" class="disk" id="disk_{{INDEX}}" value="" placeholder="_(Separate sub-folder and image will be created based on Name)_"><div class="disk_preview"></div>
|
||||
@@ -980,7 +975,7 @@
|
||||
</script>
|
||||
|
||||
<?
|
||||
$arrUnraidShares = getUnraidShares() ;
|
||||
$arrUnraidShares = getUnraidShares();
|
||||
foreach ($arrConfig['shares'] as $i => $arrShare) {
|
||||
$strLabel = ($i > 0) ? appendOrdinalSuffix($i + 1) : '';
|
||||
|
||||
@@ -996,11 +991,11 @@
|
||||
</select>
|
||||
_(Unraid Share)_:
|
||||
<select name="shares[<?=$i?>][unraid]" class="disk_bus narrow" onchange="ShareChange(this)" >
|
||||
<? $UnraidShareDisabled = ' disabled="disabled"' ;
|
||||
$arrUnraidIndex = array_search("User:".$arrShare['target'],$arrUnraidShares) ;
|
||||
if ($arrUnraidIndex != false && substr($arrShare['source'],0,10) != '/mnt/user/') $arrUnraidIndex = false ;
|
||||
if ($arrUnraidIndex == false) $arrUnraidIndex = array_search("Disk:".$arrShare['target'],$arrUnraidShares) ;
|
||||
if ($arrUnraidIndex == false) { $arrUnraidIndex = '' ; $UnraidShareDisabled = "" ;}
|
||||
<? $UnraidShareDisabled = ' disabled="disabled"';
|
||||
$arrUnraidIndex = array_search("User:".$arrShare['target'],$arrUnraidShares);
|
||||
if ($arrUnraidIndex != false && substr($arrShare['source'],0,10) != '/mnt/user/') $arrUnraidIndex = false;
|
||||
if ($arrUnraidIndex == false) $arrUnraidIndex = array_search("Disk:".$arrShare['target'],$arrUnraidShares);
|
||||
if ($arrUnraidIndex == false) { $arrUnraidIndex = ''; $UnraidShareDisabled = "";}
|
||||
mk_dropdown_options($arrUnraidShares, $arrUnraidIndex);?>
|
||||
</select>
|
||||
</td>
|
||||
@@ -1114,7 +1109,7 @@
|
||||
?>
|
||||
</select>
|
||||
<?
|
||||
if ($arrGPU['id'] != 'virtual') $multifunction = "" ; else $multifunction = " disabled " ;
|
||||
if ($arrGPU['id'] != 'virtual') $multifunction = ""; else $multifunction = " disabled ";
|
||||
?>
|
||||
<span id="GPUMulti<?=$i?>" name="gpu[<?=$i?>][multi]" class="<?if ($arrGPU['id'] != 'virtual') echo 'was';?>advanced gpumultiline<?=$i?>" >_(Multifunction)_:</span>
|
||||
|
||||
@@ -1128,10 +1123,10 @@
|
||||
</tr>
|
||||
|
||||
<?if ($i == 0) {
|
||||
$hiddenport = $hiddenwsport = "hidden" ;
|
||||
$hiddenport = $hiddenwsport = "hidden";
|
||||
if ($arrGPU['autoport'] == "no"){
|
||||
if ($arrGPU['protocol'] == "vnc") $hiddenport = $hiddenwsport = "" ;
|
||||
if ($arrGPU['protocol'] == "spice") $hiddenport = "" ;
|
||||
if ($arrGPU['protocol'] == "vnc") $hiddenport = $hiddenwsport = "";
|
||||
if ($arrGPU['protocol'] == "spice") $hiddenport = "";
|
||||
}
|
||||
?>
|
||||
<tr class="<?if ($arrGPU['id'] != 'virtual') echo 'was';?>advanced protocol">
|
||||
@@ -1164,11 +1159,11 @@
|
||||
|
||||
<span id="Porttext" <?=$hiddenport?>>_(VM Console Port)_:</span>
|
||||
|
||||
<input type="number" size="5" maxlength="5" id="port" class="narrow" style="width: 50px;" name="gpu[<?=$i?>][port]" title="_(port for virtual console)_" value="<?=$arrGPU['port']?>" <?=$hiddenport?> >
|
||||
<input type="number" size="5" maxlength="5" id="port" class="narrow" style="width: 50px;" name="gpu[<?=$i?>][port]" title="_(port for virtual console)_" value="<?=$arrGPU['port']?>" <?=$hiddenport?> >
|
||||
|
||||
<span id="WSPorttext" <?=$hiddenwsport?>>_(VM Console WS Port)_:</span>
|
||||
|
||||
<input type="number" size="5" maxlength="5" id="wsport" class="narrow" style="width: 50px;" name="gpu[<?=$i?>][wsport]" title="_(wsport for virtual console)_" value="<?=$arrGPU['wsport']?>" <?=$hiddenwsport?> >
|
||||
<input type="number" size="5" maxlength="5" id="wsport" class="narrow" style="width: 50px;" name="gpu[<?=$i?>][wsport]" title="_(wsport for virtual console)_" value="<?=$arrGPU['wsport']?>" <?=$hiddenwsport?> >
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -1329,7 +1324,7 @@
|
||||
'network' => $domain_bridge,
|
||||
'mac' => "",
|
||||
'model' => 'virtio-net'
|
||||
] ;
|
||||
];
|
||||
}
|
||||
foreach ($arrConfig['nic'] as $i => $arrNic) {
|
||||
$strLabel = ($i > 0) ? appendOrdinalSuffix($i + 1) : '';
|
||||
@@ -1419,9 +1414,7 @@
|
||||
<select name="nic[{{INDEX}}][network]">
|
||||
<?
|
||||
foreach (array_keys($arrValidNetworks) as $key) {
|
||||
|
||||
echo mk_option("", $key, "- "._($key)." -", "disabled");
|
||||
|
||||
foreach ($arrValidNetworks[$key] as $strNetwork) {
|
||||
echo mk_option($domain_bridge, $strNetwork, $strNetwork);
|
||||
}
|
||||
@@ -1497,11 +1490,10 @@
|
||||
if (!empty($arrValidOtherDevices)) {
|
||||
foreach($arrValidOtherDevices as $i => $arrDev) {
|
||||
$bootdisable = $extra = $pciboot = '';
|
||||
if ($arrDev["typeid"] != "0108" && substr($arrDev["typeid"],0,2) != "02") $bootdisable = ' disabled="disabled"' ;
|
||||
if ($arrDev["typeid"] != "0108" && substr($arrDev["typeid"],0,2) != "02") $bootdisable = ' disabled="disabled"';
|
||||
if (count($pcidevice=array_filter($arrConfig['pci'], function($arr) use ($arrDev) { return ($arr['id'] == $arrDev['id']); }))) {
|
||||
$extra .= ' checked="checked"';
|
||||
foreach ($pcidevice as $pcikey => $pcidev) $pciboot = $pcidev["boot"]; ;
|
||||
|
||||
foreach ($pcidevice as $pcikey => $pcidev) $pciboot = $pcidev["boot"];
|
||||
} elseif (!in_array($arrDev['driver'], ['pci-stub', 'vfio-pci'])) {
|
||||
//$extra .= ' disabled="disabled"';
|
||||
continue;
|
||||
@@ -1514,7 +1506,6 @@
|
||||
<?
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($intAvailableOtherPCIDevices)) {
|
||||
echo "<i>"._('None available')."</i>";
|
||||
}
|
||||
@@ -1528,8 +1519,6 @@
|
||||
<p>Use boot order to set device as bootable and boot sequence. Only NVMe and Network devices (PCI types 0108 and 02xx) supported for boot order.</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -1559,7 +1548,7 @@
|
||||
<tr>
|
||||
<td>_(QEMU Command Line)_:</td>
|
||||
<?
|
||||
if ($arrConfig['qemucmdline'] == "") $qemurows = 2 ; else $qemurows = 15 ;
|
||||
if ($arrConfig['qemucmdline'] == "") $qemurows = 2; else $qemurows = 15;
|
||||
?>
|
||||
<td>
|
||||
<textarea id="qemucmdline" name="qemucmdline" rows=<?=$qemurows?> style="width: 850px" onchange="QEMUChgCmd(this)"><?=htmlspecialchars($arrConfig['qemucmdline'])?> </textarea></td></tr>
|
||||
@@ -1576,8 +1565,8 @@
|
||||
<tr><td></td><td>_(Clocks)_</td></tr>
|
||||
<tr><td>_(Clocks Offset)_:</td>
|
||||
<td>
|
||||
<?$clockdisabled = "" ;?>
|
||||
<select name="domain[clock]" <?=$clockdisabled?> id="clockoffset" class="narrow" title="_(Clock Offset)_" <?=$arrConfig["domain"]['clock']?>>
|
||||
<?$clockdisabled = "";?>
|
||||
<select name="domain[clock]" <?=$clockdisabled?> id="clockoffset" class="narrow" title="_(Clock Offset)_" <?=$arrConfig["domain"]['clock']?>>
|
||||
<?
|
||||
echo mk_option($arrConfig['domain']['clock'], 'localtime', 'Localtime');
|
||||
echo mk_option($arrConfig['domain']['clock'], 'utc', "UTC");
|
||||
@@ -1585,18 +1574,18 @@
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<?$clockcount = 0 ;
|
||||
<?$clockcount = 0;
|
||||
if (!empty($arrClocks)) {
|
||||
foreach($arrClocks as $i => $arrTimer) {
|
||||
if ($i =="offset") continue ;
|
||||
if ($clockcount == 0) $clocksourcetext = _("Timer Source").":" ;else $clocksourcetext = "" ;
|
||||
if ($i =="offset") continue;
|
||||
if ($clockcount == 0) $clocksourcetext = _("Timer Source").":"; else $clocksourcetext = "";
|
||||
?>
|
||||
<tr><td><?=$clocksourcetext?></td>
|
||||
<td>
|
||||
<span class="narrow" style="width: 50px"><?=ucfirst($i)?>:</span></td>
|
||||
<td class="present">
|
||||
<span>_(Present)_:</span>
|
||||
<select name="clock[<?=$i?>][present]" <?=$clockdisabled?> id="clock[<?=$i?>][present]" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["present"]?>>
|
||||
<select name="clock[<?=$i?>][present]" <?=$clockdisabled?> id="clock[<?=$i?>][present]" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["present"]?>>
|
||||
<?
|
||||
echo mk_option($arrTimer["present"], 'yes', 'Yes');
|
||||
echo mk_option($arrTimer["present"], 'no', "No");
|
||||
@@ -1604,7 +1593,7 @@
|
||||
</select></td>
|
||||
<td>
|
||||
<span class="narrow" style="width: 50px">_(Tickpolicy)_:</span>
|
||||
<select name="clock[<?=$i?>][tickpolicy]" <?=$clockdisabled?> id="clock[<?=$i?>][tickpolicy]" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["tickpolicy"]?>>
|
||||
<select name="clock[<?=$i?>][tickpolicy]" <?=$clockdisabled?> id="clock[<?=$i?>][tickpolicy]" class="narrow" title="_(Clock Offset)_" <?=$arrTimer["tickpolicy"]?>>
|
||||
<?
|
||||
echo mk_option($arrTimer["tickpolicy"], 'delay', 'Delay');
|
||||
echo mk_option($arrTimer["tickpolicy"], 'catchup', 'Catchup');
|
||||
@@ -1614,7 +1603,7 @@
|
||||
</select>
|
||||
</td></tr>
|
||||
<?
|
||||
$clockcount++ ;
|
||||
$clockcount++;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1678,8 +1667,6 @@
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
</table>
|
||||
<?if ($i == 0) {?>
|
||||
<div class="advanced">
|
||||
@@ -1696,15 +1683,15 @@
|
||||
|
||||
<p>
|
||||
<b>Grab</b><br>
|
||||
All grabs all input devices instead of just one
|
||||
All grabs all input devices instead of just one
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>Repeat</b><br>
|
||||
Repeat with value 'on'/'off' to enable/disable auto-repeat events
|
||||
Repeat with value 'on'/'off' to enable/disable auto-repeat events
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<p>
|
||||
<b>GrabToggle</b><br>
|
||||
GrabToggle with values ctrl-ctrl, alt-alt, shift-shift, meta-meta, scrolllock or ctrl-scrolllock to change the grab key combination</p>
|
||||
|
||||
@@ -1758,7 +1745,6 @@
|
||||
</table>
|
||||
</script>
|
||||
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td></td>
|
||||
@@ -1819,82 +1805,82 @@
|
||||
<script type="text/javascript">
|
||||
|
||||
function ShareChange(share) {
|
||||
var value = share.value;
|
||||
var text = share.options[share.selectedIndex].text;
|
||||
var strArray = text.split(":");
|
||||
var index = share.name.indexOf("]") + 1;
|
||||
var name = share.name.substr(0,index) ;
|
||||
if (strArray[0] === "User") {
|
||||
var path = "/mnt/user/" + strArray[1] ;
|
||||
} else {
|
||||
var path = "/mnt/" + strArray[1] ;
|
||||
}
|
||||
if (strArray[0] != "Manual") {
|
||||
document.getElementById(name+"[target]").value = strArray[1] ;
|
||||
document.getElementById(name+"[source]").value = path ;
|
||||
document.getElementById(name+"[target]").setAttribute("disabled","disabled");
|
||||
document.getElementById(name+"[source]").setAttribute("disabled","disabled");
|
||||
} else {
|
||||
document.getElementById(name+"[target]").removeAttribute("disabled");
|
||||
document.getElementById(name+"[source]").removeAttribute("disabled");
|
||||
}
|
||||
var value = share.value;
|
||||
var text = share.options[share.selectedIndex].text;
|
||||
var strArray = text.split(":");
|
||||
var index = share.name.indexOf("]") + 1;
|
||||
var name = share.name.substr(0,index);
|
||||
if (strArray[0] === "User") {
|
||||
var path = "/mnt/user/" + strArray[1];
|
||||
} else {
|
||||
var path = "/mnt/" + strArray[1];
|
||||
}
|
||||
if (strArray[0] != "Manual") {
|
||||
document.getElementById(name+"[target]").value = strArray[1];
|
||||
document.getElementById(name+"[source]").value = path;
|
||||
document.getElementById(name+"[target]").setAttribute("disabled","disabled");
|
||||
document.getElementById(name+"[source]").setAttribute("disabled","disabled");
|
||||
} else {
|
||||
document.getElementById(name+"[target]").removeAttribute("disabled");
|
||||
document.getElementById(name+"[source]").removeAttribute("disabled");
|
||||
}
|
||||
}
|
||||
|
||||
function BusChange(bus) {
|
||||
var value = bus.value;
|
||||
var index = bus.name.indexOf("]") + 1;
|
||||
var name = bus.name.substr(0,index) ;
|
||||
if (value == "virtio" || value == "usb" ) {
|
||||
document.getElementById(name+"[rotatetext]").style.visibility="hidden";
|
||||
document.getElementById(name+"[rotation]").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById(name+"[rotation]").style.display="inline";
|
||||
document.getElementById(name+"[rotation]").style.visibility="visible";
|
||||
document.getElementById(name+"[rotatetext]").style.display="inline";
|
||||
document.getElementById(name+"[rotatetext]").style.visibility="visible";
|
||||
}
|
||||
var value = bus.value;
|
||||
var index = bus.name.indexOf("]") + 1;
|
||||
var name = bus.name.substr(0,index);
|
||||
if (value == "virtio" || value == "usb" ) {
|
||||
document.getElementById(name+"[rotatetext]").style.visibility="hidden";
|
||||
document.getElementById(name+"[rotation]").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById(name+"[rotation]").style.display="inline";
|
||||
document.getElementById(name+"[rotation]").style.visibility="visible";
|
||||
document.getElementById(name+"[rotatetext]").style.display="inline";
|
||||
document.getElementById(name+"[rotatetext]").style.visibility="visible";
|
||||
}
|
||||
}
|
||||
|
||||
function updateSSDCheck(ssd) {
|
||||
var value = ssd.value;
|
||||
var index = ssd.name.indexOf("]") + 1;
|
||||
var name = ssd.name.substr(0,index) ;
|
||||
if (document.getElementById(name+"[rotation]").checked) ssd.value = "1"; else ssd.value = "0";
|
||||
var value = ssd.value;
|
||||
var index = ssd.name.indexOf("]") + 1;
|
||||
var name = ssd.name.substr(0,index);
|
||||
if (document.getElementById(name+"[rotation]").checked) ssd.value = "1"; else ssd.value = "0";
|
||||
}
|
||||
|
||||
function BIOSChange(bios) {
|
||||
var value = bios.value;
|
||||
if (value == "0") {
|
||||
document.getElementById("USBBoottext").style.visibility="hidden";
|
||||
document.getElementById("domain_usbboot").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById("USBBoottext").style.display="inline";
|
||||
document.getElementById("USBBoottext").style.visibility="visible";
|
||||
document.getElementById("domain_usbboot").style.display="inline";
|
||||
document.getElementById("domain_usbboot").style.visibility="visible";
|
||||
}
|
||||
var value = bios.value;
|
||||
if (value == "0") {
|
||||
document.getElementById("USBBoottext").style.visibility="hidden";
|
||||
document.getElementById("domain_usbboot").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById("USBBoottext").style.display="inline";
|
||||
document.getElementById("USBBoottext").style.visibility="visible";
|
||||
document.getElementById("domain_usbboot").style.display="inline";
|
||||
document.getElementById("domain_usbboot").style.visibility="visible";
|
||||
}
|
||||
}
|
||||
|
||||
function QEMUChgCmd(qemu) {
|
||||
var value = qemu.value;
|
||||
if (value != "") {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","15");
|
||||
} else {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","2");
|
||||
}
|
||||
var value = qemu.value;
|
||||
if (value != "") {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","15");
|
||||
} else {
|
||||
document.getElementById("qemucmdline").setAttribute("rows","2");
|
||||
}
|
||||
}
|
||||
|
||||
function HypervChgNew(hyperv) {
|
||||
var value = hyperv.value;
|
||||
if (value == "0") {
|
||||
var clockdefault = "windows" ;
|
||||
document.getElementById("clock[rtc][present]").value = "<?=$arrDefaultClocks['windows']['rtc']['present']?>" ;
|
||||
document.getElementById("clock[pit][present]").value = "<?=$arrDefaultClocks['windows']['pit']['present']?>" ;
|
||||
} else {
|
||||
var clockdefault = "hyperv" ;
|
||||
document.getElementById("clock[rtc][present]").value = "<?=$arrDefaultClocks['hyperv']['rtc']['present']?>" ;
|
||||
document.getElementById("clock[pit][present]").value = "<?=$arrDefaultClocks['hyperv']['pit']['present']?>";
|
||||
}
|
||||
var value = hyperv.value;
|
||||
if (value == "0") {
|
||||
var clockdefault = "windows";
|
||||
document.getElementById("clock[rtc][present]").value = "<?=$arrDefaultClocks['windows']['rtc']['present']?>";
|
||||
document.getElementById("clock[pit][present]").value = "<?=$arrDefaultClocks['windows']['pit']['present']?>";
|
||||
} else {
|
||||
var clockdefault = "hyperv";
|
||||
document.getElementById("clock[rtc][present]").value = "<?=$arrDefaultClocks['hyperv']['rtc']['present']?>";
|
||||
document.getElementById("clock[pit][present]").value = "<?=$arrDefaultClocks['hyperv']['pit']['present']?>";
|
||||
}
|
||||
}
|
||||
|
||||
function SetBootorderfields(usbbootvalue) {
|
||||
@@ -1907,16 +1893,16 @@ function SetBootorderfields(usbbootvalue) {
|
||||
}
|
||||
var bootelements = document.getElementsByClassName("pcibootorder");
|
||||
const bootpcidevs = <?
|
||||
$devlist = [] ;
|
||||
$devlist = [];
|
||||
foreach($arrValidOtherDevices as $i => $arrDev) {
|
||||
if ($arrDev["typeid"] != "0108" && substr($arrDev["typeid"],0,2) != "02") $devlist[$arrDev['id']] = "N" ; else $devlist[$arrDev['id']] = "Y" ;
|
||||
if ($arrDev["typeid"] != "0108" && substr($arrDev["typeid"],0,2) != "02") $devlist[$arrDev['id']] = "N"; else $devlist[$arrDev['id']] = "Y";
|
||||
}
|
||||
echo json_encode($devlist) ;
|
||||
?>
|
||||
echo json_encode($devlist);
|
||||
?>
|
||||
|
||||
for(var i = 0; i < bootelements.length; i++) {
|
||||
let bootpciid = bootelements[i].name.split('[') ;
|
||||
bootpciid= bootpciid[1].replace(']', '') ;
|
||||
let bootpciid = bootelements[i].name.split('[');
|
||||
bootpciid= bootpciid[1].replace(']', '');
|
||||
|
||||
if (usbbootvalue == "Yes") {
|
||||
bootelements[i].value = "";
|
||||
@@ -1930,61 +1916,57 @@ function SetBootorderfields(usbbootvalue) {
|
||||
|
||||
function USBBootChange(usbboot) {
|
||||
// Remove all boot orders if changed to Yes
|
||||
var value = usbboot.value ;
|
||||
SetBootorderfields(value) ;
|
||||
var value = usbboot.value;
|
||||
SetBootorderfields(value);
|
||||
}
|
||||
|
||||
function AutoportChange(autoport) {
|
||||
if (autoport.value == "yes") {
|
||||
document.getElementById("port").style.visibility="hidden";
|
||||
document.getElementById("Porttext").style.visibility="hidden";
|
||||
if (autoport.value == "yes") {
|
||||
document.getElementById("port").style.visibility="hidden";
|
||||
document.getElementById("Porttext").style.visibility="hidden";
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
} else {
|
||||
var protocol = document.getElementById("protocol").value;
|
||||
document.getElementById("port").style.display="inline";
|
||||
document.getElementById("port").style.visibility="visible";
|
||||
document.getElementById("Porttext").style.display="inline";
|
||||
document.getElementById("Porttext").style.visibility="visible";
|
||||
if (protocol == "vnc") {
|
||||
document.getElementById("wsport").style.display="inline";
|
||||
document.getElementById("wsport").style.visibility="visible";
|
||||
document.getElementById("WSPorttext").style.display="inline";
|
||||
document.getElementById("WSPorttext").style.visibility="visible";
|
||||
} else {
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
} else {
|
||||
var protocol = document.getElementById("protocol").value ;
|
||||
document.getElementById("port").style.display="inline";
|
||||
document.getElementById("port").style.visibility="visible";
|
||||
document.getElementById("Porttext").style.display="inline";
|
||||
document.getElementById("Porttext").style.visibility="visible";
|
||||
if (protocol == "vnc") {
|
||||
document.getElementById("wsport").style.display="inline";
|
||||
document.getElementById("wsport").style.visibility="visible";
|
||||
document.getElementById("WSPorttext").style.display="inline";
|
||||
document.getElementById("WSPorttext").style.visibility="visible";
|
||||
} else {
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ProtocolChange(protocol) {
|
||||
var autoport = document.getElementById("autoport").value ;
|
||||
if (autoport == "yes") {
|
||||
document.getElementById("port").style.visibility="hidden";
|
||||
document.getElementById("Porttext").style.visibility="hidden";
|
||||
var autoport = document.getElementById("autoport").value;
|
||||
if (autoport == "yes") {
|
||||
document.getElementById("port").style.visibility="hidden";
|
||||
document.getElementById("Porttext").style.visibility="hidden";
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById("port").style.display="inline";
|
||||
document.getElementById("port").style.visibility="visible";
|
||||
document.getElementById("Porttext").style.display="inline";
|
||||
document.getElementById("Porttext").style.visibility="visible";
|
||||
if (protocol.value == "vnc") {
|
||||
document.getElementById("wsport").style.display="inline";
|
||||
document.getElementById("wsport").style.visibility="visible";
|
||||
document.getElementById("WSPorttext").style.display="inline";
|
||||
document.getElementById("WSPorttext").style.visibility="visible";
|
||||
} else {
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
} else {
|
||||
document.getElementById("port").style.display="inline";
|
||||
document.getElementById("port").style.visibility="visible";
|
||||
document.getElementById("Porttext").style.display="inline";
|
||||
document.getElementById("Porttext").style.visibility="visible";
|
||||
if (protocol.value == "vnc") {
|
||||
document.getElementById("wsport").style.display="inline";
|
||||
document.getElementById("wsport").style.visibility="visible";
|
||||
document.getElementById("WSPorttext").style.display="inline";
|
||||
document.getElementById("WSPorttext").style.visibility="visible";
|
||||
} else {
|
||||
document.getElementById("wsport").style.visibility="hidden";
|
||||
document.getElementById("WSPorttext").style.visibility="hidden";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
$(function() {
|
||||
function completeAfter(cm, pred) {
|
||||
@@ -2012,7 +1994,6 @@ $(function() {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("addcode"), {
|
||||
mode: "xml",
|
||||
lineNumbers: true,
|
||||
@@ -2028,7 +2009,7 @@ $(function() {
|
||||
hintOptions: {schemaInfo: getLibvirtSchema()}
|
||||
});
|
||||
|
||||
SetBootorderfields("<?=$arrConfig['domain']['usbboot']?>") ;
|
||||
SetBootorderfields("<?=$arrConfig['domain']['usbboot']?>");
|
||||
|
||||
function resetForm() {
|
||||
$("#vmform .domain_vcpu").change(); // restore the cpu checkbox disabled states
|
||||
@@ -2052,7 +2033,6 @@ $(function() {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var regenerateDiskPreview = function (disk_index) {
|
||||
var domaindir = '<?=$domain_cfg['DOMAINDIR']?>' + $('#domain_oldname').val();
|
||||
var tl_args = arguments.length;
|
||||
@@ -2072,7 +2052,7 @@ $(function() {
|
||||
var $disk_serial = $table.find('.disk_serial');
|
||||
var $disk_driver = $table.find('.disk_driver').val();
|
||||
var $disk_ext = "img";
|
||||
if ($disk_driver == "raw") $disk_ext = "img";
|
||||
if ($disk_driver == "raw") $disk_ext = "img";
|
||||
else if(disk_select != 'manual') $disk_ext = $disk_driver;
|
||||
|
||||
if (disk_select == 'manual') {
|
||||
@@ -2089,18 +2069,14 @@ $(function() {
|
||||
if (info.isfile || info.isblock) {
|
||||
slideUpRows($disk_file_sections);
|
||||
$disk_file_sections.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
|
||||
|
||||
$disk_input.attr('name', $disk_input.attr('name').replace('new', 'image'));
|
||||
} else {
|
||||
$disk_file_sections.filter('.wasadvanced').removeClass('wasadvanced').addClass('advanced');
|
||||
slideDownRows($disk_file_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
|
||||
|
||||
$disk_input.attr('name', $disk_input.attr('name').replace('image', 'new'));
|
||||
}
|
||||
});
|
||||
|
||||
} else if (disk_select !== '') {
|
||||
|
||||
// Auto disk
|
||||
var auto_disk_path = domaindir + '/vdisk' + (index+1) + '.' + $disk_ext;
|
||||
$disk_preview.html(auto_disk_path);
|
||||
@@ -2124,15 +2100,12 @@ $(function() {
|
||||
$disk_input.attr('name', $disk_input.attr('name').replace('image', 'new'));
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
// No disk
|
||||
var $hide_el = $table.find('.disk_bus_options,.disk_file_options,.disk_preview,.disk');
|
||||
$disk_preview.html('');
|
||||
slideUpRows($hide_el);
|
||||
$hide_el.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -2154,11 +2127,9 @@ $(function() {
|
||||
if (disk_select !== '') {
|
||||
|
||||
// Auto disk serial
|
||||
var auto_serial = 'vdisk' + (index+1) ;
|
||||
var auto_serial = 'vdisk' + (index+1);
|
||||
$disk_serial.val(auto_serial);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2209,7 +2180,7 @@ $(function() {
|
||||
$("#vmform").on("spawn_section", function spawnSectionEvent(evt, section, sectiondata) {
|
||||
if (sectiondata.category == 'vDisk') {
|
||||
regenerateDiskPreview(sectiondata.index);
|
||||
setDiskserial(sectiondata.index) ;
|
||||
setDiskserial(sectiondata.index);
|
||||
}
|
||||
if (sectiondata.category == 'Graphics_Card') {
|
||||
$(section).find(".gpu").change();
|
||||
@@ -2250,8 +2221,8 @@ $(function() {
|
||||
$("#vmform").on("change", ".cpu", function changeCPUEvent() {
|
||||
var myvalue = $(this).val();
|
||||
var mylabel = $(this).children('option:selected').text();
|
||||
var cpumigrate = document.getElementById("domain_cpumigrate_text") ;
|
||||
var cpumigrate_text = document.getElementById("domain_cpumigrate") ;
|
||||
var cpumigrate = document.getElementById("domain_cpumigrate_text");
|
||||
var cpumigrate_text = document.getElementById("domain_cpumigrate");
|
||||
if (myvalue == "custom") {
|
||||
document.getElementById("domain_cpumigrate_text").style.visibility="hidden";
|
||||
document.getElementById("domain_cpumigrate").style.visibility="hidden";
|
||||
@@ -2261,8 +2232,7 @@ $(function() {
|
||||
document.getElementById("domain_cpumigrate").style.display="inline";
|
||||
document.getElementById("domain_cpumigrate").style.visibility="visible";
|
||||
}
|
||||
|
||||
}) ;
|
||||
});
|
||||
|
||||
$("#vmform").on("change", ".gpu", function changeGPUEvent() {
|
||||
var myvalue = $(this).val();
|
||||
@@ -2274,13 +2244,13 @@ $(function() {
|
||||
if (myvalue == 'virtual') {
|
||||
$vnc_sections.filter('.wasadvanced').removeClass('wasadvanced').addClass('advanced');
|
||||
slideDownRows($vnc_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
|
||||
var MultiSel = document.getElementById("GPUMultiSel0") ;
|
||||
MultiSel.disabled = true ;
|
||||
var MultiSel = document.getElementById("GPUMultiSel0");
|
||||
MultiSel.disabled = true;
|
||||
} else {
|
||||
slideUpRows($vnc_sections);
|
||||
$vnc_sections.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
|
||||
var MultiSel = document.getElementById("GPUMultiSel0") ;
|
||||
MultiSel.disabled = false ;
|
||||
var MultiSel = document.getElementById("GPUMultiSel0");
|
||||
MultiSel.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2388,7 +2358,6 @@ $(function() {
|
||||
form.append('<input type="hidden" name="createvmtemplate" value="1" />');
|
||||
var createVmInput = form.find('input[name="createvm"],input[name="updatevm"]');
|
||||
createVmInput.remove();
|
||||
|
||||
|
||||
$("#vmform .disk_select option:selected").not("[value='manual']").closest('table').each(function () {
|
||||
var v = $(this).find('.disk_preview').html();
|
||||
@@ -2435,20 +2404,17 @@ $(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)_:\n_(If name already exists it will be replaced)_.",
|
||||
type: "input",
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false,
|
||||
//animation: "slide-from-top",
|
||||
inputPlaceholder: _("Leaving blank will use OS name.")_
|
||||
},
|
||||
function(inputValue){
|
||||
|
||||
|
||||
postdata=postdata+"&templatename="+inputValue;
|
||||
|
||||
$.post("/plugins/dynamix.vm.manager/templates/Custom.form.php", postdata, function( data ) {
|
||||
inputPlaceholder: "_(Leaving blank will use OS name)_."
|
||||
},
|
||||
function(inputValue){
|
||||
postdata=postdata+"&templatename="+inputValue;
|
||||
$.post("/plugins/dynamix.vm.manager/templates/Custom.form.php", postdata, function( data ) {
|
||||
if (data.success) {
|
||||
if (data.vmrcurl) {
|
||||
var vmrc_window=window.open(data.vmrcurl, '_blank', 'scrollbars=yes,resizable=yes');
|
||||
@@ -2516,18 +2482,17 @@ $(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)_:\n_(If 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;
|
||||
postdata=postdata+"&templatename="+inputValue;
|
||||
|
||||
$.post("/plugins/dynamix.vm.manager/templates/Custom.form.php", postdata, function( data ) {
|
||||
if (data.success) {
|
||||
|
||||
@@ -4,8 +4,8 @@ Tag="snowflake-o"
|
||||
Nchan="device_list,disk_load,parity_list"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -113,9 +113,9 @@ function toggle_state(device,name,action) {
|
||||
}
|
||||
function display_diskio() {
|
||||
if ($.cookie('diskio')===undefined) {
|
||||
$('span.number').show(); $('span.diskio').hide();
|
||||
} else {
|
||||
$('span.diskio').show(); $('span.number').hide();
|
||||
} else {
|
||||
$('span.number').show(); $('span.diskio').hide();
|
||||
}
|
||||
}
|
||||
function toggle_diskio(init) {
|
||||
@@ -123,9 +123,9 @@ function toggle_diskio(init) {
|
||||
if ($.cookie('diskio')===undefined) $.cookie('diskio','diskio',{expires:3650}); else $.removeCookie('diskio');
|
||||
}
|
||||
if ($.cookie('diskio')===undefined) {
|
||||
$('i.toggle').removeClass('fa-tachometer').addClass('fa-list');
|
||||
} else {
|
||||
$('i.toggle').removeClass('fa-list').addClass('fa-tachometer');
|
||||
} else {
|
||||
$('i.toggle').removeClass('fa-tachometer').addClass('fa-list');
|
||||
}
|
||||
display_diskio();
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ Menu="Dashboard"
|
||||
Nchan="wg_poller,update_1,update_2,update_3,ups_status:stop,vm_dashusage"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -55,29 +55,29 @@ exec("sed -ri 's/^\.logLine\{color:#......;/.logLine{color:$fgcolor;/' $docroot/
|
||||
exec("/etc/rc.d/rc.docker status >/dev/null",$dummy,$dockerd);
|
||||
exec("/etc/rc.d/rc.libvirt status >/dev/null",$dummy,$libvirtd);
|
||||
|
||||
$dockerd = $dockerd==0;
|
||||
$libvirtd = $libvirtd==0;
|
||||
$apcupsd = file_exists('/var/run/apcupsd.pid');
|
||||
$conf = glob('/etc/wireguard/wg*.conf');
|
||||
$wireguard = is_executable('/usr/bin/wg') && count($conf);
|
||||
$started = _var($var,'fsState')=='Started';
|
||||
$sleep = isset($display['sleep']);
|
||||
$dockerd = $dockerd==0;
|
||||
$libvirtd = $libvirtd==0;
|
||||
$apcupsd = file_exists('/var/run/apcupsd.pid');
|
||||
$cookie = '/boot/config/dashboard_settings.json';
|
||||
$conf = glob('/etc/wireguard/wg*.conf');
|
||||
$wireguard = is_executable('/usr/bin/wg') && count($conf);
|
||||
$started = _var($var,'fsState')=='Started';
|
||||
$sleep = isset($display['sleep']);
|
||||
$poolsOnly = (_var($var,'SYS_ARRAY_SLOTS') == 0 ) ? true : false;
|
||||
$array_size = $array_used = 0;
|
||||
$extra_size = $extra_used = 0;
|
||||
$cache_size = $cache_used = [];
|
||||
$cache_type = $cache_rate = [];
|
||||
|
||||
$parity = _var($var,'mdResync');
|
||||
$mover = file_exists('/var/run/mover.pid');
|
||||
$btrfs = exec('pgrep --ns $$ -cf /sbin/btrfs');
|
||||
$vdisk = exec("grep -Pom1 '^DOCKER_IMAGE_TYPE=\"\\K[^\"]+' /boot/config/docker.cfg 2>/dev/null")!='folder' ? _('Docker vdisk') : _('Docker folder');
|
||||
$dot = _var($display,'number','.,')[0];
|
||||
$zfs = count(array_filter(array_column($disks,'fsType'),function($fs){return str_replace('luks:','',$fs??'')=='zfs';}));
|
||||
$parity = _var($var,'mdResync');
|
||||
$mover = file_exists('/var/run/mover.pid');
|
||||
$btrfs = exec('pgrep --ns $$ -cf /sbin/btrfs');
|
||||
$vdisk = exec("grep -Pom1 '^DOCKER_IMAGE_TYPE=\"\\K[^\"]+' /boot/config/docker.cfg 2>/dev/null")!='folder' ? _('Docker vdisk') : _('Docker folder');
|
||||
$dot = _var($display,'number','.,')[0];
|
||||
$zfs = count(array_filter(array_column($disks,'fsType'),function($fs){return str_replace('luks:','',$fs??'')=='zfs';}));
|
||||
|
||||
$domain_cfgfile = "/boot/config/domain.cfg";
|
||||
$domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
if (!isset($domain_cfg['USAGE'])) $vmusage = "N" ; else $vmusage = $domain_cfg['USAGE'];
|
||||
$vmusage = isset($domain_cfg['USAGE']) ? $domain_cfg['USAGE'] : 'N';
|
||||
|
||||
// enable/disable graph elements by making hook script executable or not
|
||||
chmod("$docroot/webGui/system/VM",$libvirtd ? 0755 : 0644);
|
||||
@@ -103,45 +103,50 @@ foreach ($disks as $disk) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($devs as $disk) {
|
||||
$extra_size += _var($disk,'sectors',0)*_var($disk,'sector_size',0);
|
||||
}
|
||||
|
||||
$array_percent = number_format(100*$array_used/($array_size ?: 1),1,$dot,'');
|
||||
exec('cat /sys/devices/system/cpu/*/topology/thread_siblings_list|sort -nu', $cpus);
|
||||
$wg_up = $wireguard ? exec("wg show interfaces") : '';
|
||||
$wg_up = $wg_up ? explode(' ',$wg_up) : [];
|
||||
$up = count($wg_up);
|
||||
$down = max(count($conf)-$up,0);
|
||||
$fans = exec("sensors -uA 2>/dev/null|grep -c 'fan[0-9]_input'");
|
||||
$autofan = is_executable("$docroot/plugins/dynamix.system.autofan/scripts/rc.autofan");
|
||||
$group = _var($var,'shareSMBEnabled')=='yes' | _var($var,'shareNFSEnabled')=='yes';
|
||||
$names = [];
|
||||
$wg_up = $wireguard ? exec("wg show interfaces") : '';
|
||||
$wg_up = $wg_up ? explode(' ',$wg_up) : [];
|
||||
$up = count($wg_up);
|
||||
$down = max(count($conf)-$up,0);
|
||||
$fans = exec("sensors -uA 2>/dev/null|grep -c 'fan[0-9]_input'");
|
||||
$autofan = is_executable("$docroot/plugins/dynamix.system.autofan/scripts/rc.autofan");
|
||||
$group = _var($var,'shareSMBEnabled')=='yes' | _var($var,'shareNFSEnabled')=='yes';
|
||||
$names = [];
|
||||
$cache_only = $encrypted = 0;
|
||||
|
||||
foreach ($shares as $share) {
|
||||
if ($share['useCache']=='only') $cache_only++;
|
||||
if ($share['luksStatus']>0) $encrypted++;
|
||||
}
|
||||
|
||||
$passwd = $nopass = 0;
|
||||
foreach ($users as $user) if ($user['passwd']=='yes') $passwd++; else $nopass++;
|
||||
|
||||
$boot = "/boot/config/plugins/dynamix";
|
||||
$myfile = "case-model.cfg";
|
||||
$mycase = file_exists("$boot/$myfile") ? file_get_contents("$boot/$myfile") : false;
|
||||
$boot = "/boot/config/plugins/dynamix";
|
||||
$myfile = "case-model.cfg";
|
||||
$mycase = file_exists("$boot/$myfile") ? file_get_contents("$boot/$myfile") : false;
|
||||
|
||||
$board = dmidecode('Base Board Information','2',0);
|
||||
$serial = _("s/n").": ".($board['Serial Number'] ?? "--");
|
||||
$board = ($board['Manufacturer'] ?? "").' '.($board['Product Name'] ?? "").' '.(isset($board['Version']) ? ", "._("Version")." ".$board['Version'] : "");
|
||||
$board = dmidecode('Base Board Information','2',0);
|
||||
$serial = _("s/n").": ".($board['Serial Number'] ?? "--");
|
||||
$board = ($board['Manufacturer'] ?? "").' '.($board['Product Name'] ?? "").' '.(isset($board['Version']) ? ", "._("Version")." ".$board['Version'] : "");
|
||||
|
||||
$bios = dmidecode('BIOS Information','0',0);
|
||||
$bios = dmidecode('BIOS Information','0',0);
|
||||
$biosdate = _("BIOS dated").": "._(my_time(strtotime($bios['Release Date'] ?? ""),$display['date']),0);
|
||||
$bios = $bios['Vendor'].(isset($bios['Version']) ? ", "._("Version")." ".$bios['Version'] : "");
|
||||
$bios = $bios['Vendor'].(isset($bios['Version']) ? ", "._("Version")." ".$bios['Version'] : "");
|
||||
|
||||
$cpu = dmidecode('Processor Information','4',0);
|
||||
$cpu = dmidecode('Processor Information','4',0);
|
||||
$cpumodel = str_ireplace(["Processor","(C)","(R)","(TM)"],["","©","®","™"],exec("grep -Pom1 '^model name\s+:\s*\K.+' /proc/cpuinfo") ?: $cpu['Version']);
|
||||
$cpumodel .= (strpos($cpumodel,'@')===false && !empty($cpu['Current Speed']) ? " @ {$cpu['Current Speed']}" : "");
|
||||
|
||||
$total = exec("awk '/^MemTotal/{print $2*1024}' /proc/meminfo");
|
||||
unset($ports); exec("ls /sys/class/net|grep -Po '^(lo|(bond|eth)\d+)$'",$ports);
|
||||
unset($ports); exec("ls --indicator-style=none /sys/class/net|grep -Po '^(bond|eth|wlan)\d+$'",$ports);
|
||||
$ports[] = 'lo';
|
||||
|
||||
$sizes = ['MB','GB','TB'];
|
||||
$memory_type = $ecc = '';
|
||||
@@ -198,7 +203,7 @@ switch ($theme) {
|
||||
<div class='frame'>
|
||||
<div class='grid'>
|
||||
<div class='tile' id='tile1'>
|
||||
<table id='db-box1' class='dashboard'>
|
||||
<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><?=htmlspecialchars(_var($var,'COMMENT'))?></span><span id="current_time_" class="switch head_time"></span><br></div>
|
||||
@@ -412,7 +417,7 @@ echo "</td></tr>";
|
||||
</div>
|
||||
|
||||
<div class='tile' id='tile2'>
|
||||
<table id='db-box2' class='dashboard'>
|
||||
<table id='db_box2' class='dashboard'>
|
||||
<?if ($dockerd):?>
|
||||
<tbody id='docker_view' title="_(Docker Containers)_" data="noApps()">
|
||||
<tr><td><i class='icon-docker f32'></i><div class='section'>_(Docker Containers)_<br>
|
||||
@@ -574,7 +579,7 @@ if (!$group) {
|
||||
</div>
|
||||
|
||||
<div class='tile' id='tile3'>
|
||||
<table id='db-box3' class='dashboard'>
|
||||
<table id='db_box3' class='dashboard'>
|
||||
<?if (!$poolsOnly):?>
|
||||
<tbody title="_(Parity Information)_">
|
||||
<tr><td><i class='icon-health f32'></i><div class='section'>_(Parity)_<br>
|
||||
@@ -653,7 +658,7 @@ for (let n=0,x; x=index[n]; n++) {
|
||||
}
|
||||
function hideShow() {
|
||||
let n = 0, inactive = [];
|
||||
var count = {'db-box1':0, 'db-box2':0, 'db-box3':0};
|
||||
var count = {'db_box1':0, 'db_box2':0, 'db_box3':0};
|
||||
$('input.checker').each(function(){
|
||||
var tbody = $('table.dashboard').find('tbody[sort="'+sort[n]+'"]');
|
||||
var id = tbody.parent().prop('id');
|
||||
@@ -669,14 +674,15 @@ function hideShow() {
|
||||
n++;
|
||||
});
|
||||
count[table.find('tbody.system').parent().prop('id')]++;
|
||||
if (count['db-box1']>0) $('div#tile1').show(); else $('div#tile1').hide();
|
||||
if (count['db-box2']>0) $('div#tile2').show(); else $('div#tile2').hide();
|
||||
if (count['db-box3']>0) $('div#tile3').show(); else $('div#tile3').hide();
|
||||
if (count['db_box1']>0) $('div#tile1').show(); else $('div#tile1').hide();
|
||||
if (count['db_box2']>0) $('div#tile2').show(); else $('div#tile2').hide();
|
||||
if (count['db_box3']>0) $('div#tile3').show(); else $('div#tile3').hide();
|
||||
if (inactive.length>0) {
|
||||
$.cookie('inactive_content',inactive.join(';'),{expires:3650});
|
||||
cookie.inactive_content = inactive.join(';');
|
||||
} else {
|
||||
$.removeCookie('inactive_content');
|
||||
delete cookie.inactive_content;
|
||||
}
|
||||
saveCookie();
|
||||
}
|
||||
</script>
|
||||
<div id="list"></div>
|
||||
@@ -753,8 +759,8 @@ String.prototype.md5 = function(){
|
||||
return rh(a)+rh(b)+rh(c)+rh(d);
|
||||
}
|
||||
jQuery.prototype.hideMe = function() {
|
||||
var hidden = $.cookie('hidden_content');
|
||||
hidden = hidden==null ? [] : hidden.split(';');
|
||||
var hidden = cookie.hidden_content;
|
||||
hidden = hidden ? hidden.split(';') : [];
|
||||
if (hidden.indexOf(this.attr('sort'))>=0) this.find('tr:gt(0)').hide();
|
||||
}
|
||||
jQuery.prototype.mixedView = function(s) {
|
||||
@@ -779,29 +785,12 @@ jQuery.prototype.mixedView = function(s) {
|
||||
});
|
||||
}
|
||||
}
|
||||
function sanitizeMultiCookie(cookieName, delimiter, removeDuplicates = false) {
|
||||
// Some browser states leave multi-value cookies with nulls, empties or duplicates.
|
||||
// This function cleans up any such cookies so that they do not break functionality.
|
||||
try {
|
||||
var uncleanCookie = $.cookie(cookieName);
|
||||
if (uncleanCookie) {
|
||||
uncleanCookie = uncleanCookie.split(delimiter);
|
||||
var cleanCookie = uncleanCookie.filter(n => n);
|
||||
if (removeDuplicates) { cleanCookie = [...new Set(cleanCookie)]; }
|
||||
if (JSON.stringify(uncleanCookie) !== JSON.stringify(cleanCookie)) {
|
||||
$.cookie(cookieName,cleanCookie.join(delimiter),{expires:3650});
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
<?if (file_exists($cookie)):?>
|
||||
var cookie = JSON.parse('<?=file_get_contents($cookie)?>');
|
||||
<?else:?>
|
||||
var cookie = {};
|
||||
<?endif;?>
|
||||
var colors = ['<?=$c0?>','<?=$c1?>','#d77e0d','#d4ac0d','#cd5c5c','#ffc0cb','#e6e6fa','#9370db','#7cfc00','#228b22','#00ffff','#4682b4'];
|
||||
var blue = '#486dba'; // fallback color when too many graph elements exist
|
||||
var ports = [<?=implode(',',array_map('escapestring',$ports))?>];
|
||||
@@ -810,8 +799,8 @@ var rxd = [];
|
||||
var txd = [];
|
||||
var cputime = 0;
|
||||
var nettime = 0;
|
||||
var cpuline = $.cookie('cpuline')||30;
|
||||
var netline = $.cookie('netline')||30;
|
||||
var cpuline = cookie.cpuline||30;
|
||||
var netline = cookie.netline||30;
|
||||
var update2 = true;
|
||||
var box = null;
|
||||
var startup = true;
|
||||
@@ -849,8 +838,38 @@ var options_net = {
|
||||
var cpuchart = new ApexCharts(document.querySelector('#cpuchart'), options_cpu);
|
||||
var netchart = new ApexCharts(document.querySelector('#netchart'), options_net);
|
||||
|
||||
if ($.cookie('port_select')!=null && !ports.includes($.cookie('port_select'))) $.removeCookie('port_select');
|
||||
var port_select = $.cookie('port_select')||ports[0];
|
||||
if (cookie.port_select && !ports.includes(cookie.port_select)) {
|
||||
delete cookie.port_select;
|
||||
saveCookie();
|
||||
}
|
||||
var port_select = cookie.port_select||ports[0];
|
||||
|
||||
function saveCookie() {
|
||||
$.post('/webGui/include/InitCharts.php',{cmd:'cookie',data:JSON.stringify(cookie)});
|
||||
}
|
||||
|
||||
function sanitizeMultiCookie(cookieName, delimiter, removeDuplicates=false) {
|
||||
// Some browser states leave multi-value cookies with nulls, empties or duplicates.
|
||||
// This function cleans up any such cookies so that they do not break functionality.
|
||||
try {
|
||||
var uncleanCookie = $.cookie(cookieName);
|
||||
if (uncleanCookie) {
|
||||
uncleanCookie = uncleanCookie.split(delimiter);
|
||||
var cleanCookie = uncleanCookie.filter(n => n);
|
||||
if (removeDuplicates) { cleanCookie = [...new Set(cleanCookie)]; }
|
||||
if (JSON.stringify(uncleanCookie) !== JSON.stringify(cleanCookie)) {
|
||||
$.cookie(cookieName,cleanCookie.join(delimiter),{expires:3650});
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function initCharts(clear) {
|
||||
$.post('/webGui/include/InitCharts.php',{cmd:'get'},function(data) {
|
||||
@@ -879,12 +898,14 @@ function initCharts(clear) {
|
||||
nettime = x + 1;
|
||||
});
|
||||
}
|
||||
|
||||
function resetCharts() {
|
||||
// prevent unlimited graph growing
|
||||
cpu = cpu.slice(-cpuline);
|
||||
rxd = rxd.slice(-netline);
|
||||
txd = txd.slice(-netline);
|
||||
}
|
||||
|
||||
function addChartCpu(load) {
|
||||
cputime++;
|
||||
var i = cpu.length - cpuline;
|
||||
@@ -895,6 +916,7 @@ function addChartCpu(load) {
|
||||
}
|
||||
cpu.push({x:cputime, y:load});
|
||||
}
|
||||
|
||||
function addChartNet(rx, tx) {
|
||||
nettime++;
|
||||
var i = rxd.length - netline;
|
||||
@@ -908,6 +930,7 @@ function addChartNet(rx, tx) {
|
||||
rxd.push({x:nettime, y:rx});
|
||||
txd.push({x:nettime, y:tx});
|
||||
}
|
||||
|
||||
<?if ($wireguard):?>
|
||||
function toggleVPN(id,vtun) {
|
||||
var up = $('#vpn-active');
|
||||
@@ -928,23 +951,28 @@ function toggleVPN(id,vtun) {
|
||||
}
|
||||
}
|
||||
<?endif;?>
|
||||
|
||||
function noApps() {
|
||||
if ($('span.outer.apps:visible').length==0) $('#no_apps').show(); else $('#no_apps').hide();
|
||||
}
|
||||
|
||||
function noVMs() {
|
||||
if ($('span.outer.vms:visible').length==0) $('#no_vms').show(); else $('#no_vms').hide();
|
||||
}
|
||||
|
||||
function loadlist(init) {
|
||||
if (init) {
|
||||
$('#apps').switchButton({labels_placement:'right', off_label:"_(All Apps)_", on_label:"_(Started only)_", checked:$.cookie('my_apps')=='startedOnly'});
|
||||
$('#vms').switchButton({labels_placement:'right', off_label:"_(All VMs)_", on_label:"_(Started only)_", checked:$.cookie('my_vms')=='startedOnly'});
|
||||
$('#apps').switchButton({labels_placement:'right', off_label:"_(All Apps)_", on_label:"_(Started only)_", checked:cookie.my_apps=='startedOnly'});
|
||||
$('#vms').switchButton({labels_placement:'right', off_label:"_(All VMs)_", on_label:"_(Started only)_", checked:cookie.my_vms=='startedOnly'});
|
||||
$('#apps').change(function(){
|
||||
$('span.outer.apps.stopped').finish().toggle('fast',function(){noApps();})
|
||||
$('#apps').is(':checked') ? $.cookie('my_apps','startedOnly',{expires:3650}) : $.removeCookie('my_apps');
|
||||
$('#apps').is(':checked') ? cookie.my_apps = 'startedOnly' : delete cookie.my_apps;
|
||||
saveCookie();
|
||||
});
|
||||
$('#vms').change(function(){
|
||||
$('span.outer.vms.stopped').finish().toggle('fast',function(){noVMs();});
|
||||
$('#vms').is(':checked') ? $.cookie('my_vms','startedOnly',{expires:3650}) : $.removeCookie('my_vms');
|
||||
$('#vms').is(':checked') ? cookie.my_vms = 'startedOnly' : delete cookie.my_vms;
|
||||
saveCookie();
|
||||
});
|
||||
}
|
||||
$.post('/webGui/include/DashboardApps.php',{docker:'<?=$dockerd?>',vms:'<?=$libvirtd?>',vmusage:'<?=$vmusage?>'},function(d) {
|
||||
@@ -963,10 +991,11 @@ function loadlist(init) {
|
||||
$('#vm_view_usage').append(data[2]).hideMe();
|
||||
$('.apps.switch').html("_(Containers)_ -- _(Started)_: "+started_apps+", _(Stopped)_: "+stopped_apps+", _(Paused)_: "+paused_apps);
|
||||
$('.vms.switch').html("_(VMs)_ -- _(Started)_: "+started_vms+", _(Stopped)_: "+stopped_vms+", _(Paused)_: "+paused_vms);
|
||||
if ($.cookie('my_apps')!=null) $('span.apps.stopped').hide(0,noApps());
|
||||
if ($.cookie('my_vms')!=null) $('span.vms.stopped').hide(0,noVMs());
|
||||
if (cookie.my_apps!=null) $('span.apps.stopped').hide(0,noApps());
|
||||
if (cookie.my_vms!=null) $('span.vms.stopped').hide(0,noVMs());
|
||||
});
|
||||
}
|
||||
|
||||
function getCase() {
|
||||
$.post('/webGui/include/SelectCase.php',{mode:'get',file:'<?=$myfile?>'},function(model){
|
||||
if (!model) {
|
||||
@@ -979,8 +1008,10 @@ function getCase() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function changeMode(item) {
|
||||
if (item==0) $.removeCookie('enter_share'); else $.cookie('enter_share',item,{expires:3650});
|
||||
if (item==0) delete cookie.enter_share; else cookie.enter_share = item;
|
||||
if (!startup) saveCookie();
|
||||
<?if (_var($var,'shareSMBEnabled')=='yes'):?>
|
||||
if (startup || $('.smb.share1').parent().find('tr:eq(1)').is(':visible')) {
|
||||
if (item==0) $('.smb.share1').show(); else $('.smb.share1').hide();
|
||||
@@ -999,23 +1030,30 @@ function changeMode(item) {
|
||||
<?endif;?>
|
||||
$('select[name="enter_user"]').val(item);
|
||||
}
|
||||
|
||||
function changeView(item) {
|
||||
if (item==0) $.removeCookie('enter_view'); else $.cookie('enter_view',item,{expires:3650});
|
||||
if (item==0) delete cookie.enter_view; else cookie.enter_view = item;
|
||||
if (!startup) saveCookie();
|
||||
if (item==0) $('.view1').show(); else $('.view1').hide();
|
||||
if (item==1) $('.view2').show(); else $('.view2').hide();
|
||||
if (item==2) $('.view3').show(); else $('.view3').hide();
|
||||
if (item==3) $('.view4').show(); else $('.view4').hide();
|
||||
}
|
||||
|
||||
function changeCPUline(val) {
|
||||
cpuline = val;
|
||||
if (val==30) $.removeCookie('cpuline'); else $.cookie('cpuline',val,{expires:3650});
|
||||
if (val==30) delete cookie.cpuline; else cookie.cpuline = val;
|
||||
saveCookie();
|
||||
cpuchart.updateOptions({xaxis:{range:cpuline-1}});
|
||||
}
|
||||
|
||||
function changeNetline(val) {
|
||||
netline = val;
|
||||
if (val==30) $.removeCookie('netline'); else $.cookie('netline',val,{expires:3650});
|
||||
if (val==30) delete cookie.netline; else cookie.netline = val;
|
||||
saveCookie();
|
||||
netchart.updateOptions({xaxis:{range:netline-1}});
|
||||
}
|
||||
|
||||
function smartMenu(table) {
|
||||
$(table).find('[id^="smart-"]').each(function() {
|
||||
var opts = [];
|
||||
@@ -1037,6 +1075,7 @@ function smartMenu(table) {
|
||||
context.attach(id,opts);
|
||||
});
|
||||
}
|
||||
|
||||
function portMenu() {
|
||||
var select = 'select[name="port_select"]';
|
||||
var option = $(select+' option');
|
||||
@@ -1044,11 +1083,14 @@ function portMenu() {
|
||||
if (option[i].value == port_select) {option[i].selected = true; break;}
|
||||
}
|
||||
}
|
||||
|
||||
function portSelect(name) {
|
||||
$.cookie('port_select',name,{expires:3650});
|
||||
cookie.port_select = name;
|
||||
saveCookie();
|
||||
initCharts(true);
|
||||
port_select = name;
|
||||
}
|
||||
|
||||
function moreInfo(data,table) {
|
||||
var info = [];
|
||||
if (data[1]>0) info.push(data[1]+' '+(data[1]==1 ? "_(device warning)_" : "_(device warnings)_"));
|
||||
@@ -1057,6 +1099,7 @@ function moreInfo(data,table) {
|
||||
if (data[4]>0) info.push(data[4]+' '+(data[4]==1 ? "_(utilization warning)_" : "_(utilization warnings)_"));
|
||||
return info.length ? "<div class='last'><i class='icon-u-triangle failed'></i><span class='failed'>"+table+" _(has)_ "+info.join('. ')+".</span></div>" : "";
|
||||
}
|
||||
|
||||
function autoscale(value,text,size,kilo) {
|
||||
if (kilo==null) kilo = 1000;
|
||||
var unit = kilo==1024 ? ['','ki','Mi','Gi','Ti','Pi','Ei'] : ['','k','M','G','T','P','E'];
|
||||
@@ -1066,42 +1109,52 @@ function autoscale(value,text,size,kilo) {
|
||||
if (data==0) base=0;
|
||||
return ((Math.round(scale*data)/scale)+' '+unit[base]+text).replace(".","<?=_var($display,'number','.,')[0]?>");
|
||||
}
|
||||
|
||||
function update900() {
|
||||
// prevent chart overflowing, reset every 15 minutes
|
||||
resetCharts();
|
||||
setTimeout(update900,900000);
|
||||
}
|
||||
|
||||
function attributes(page,disk) {
|
||||
var tab = page=='New' ? 'tab2' : 'tab3';
|
||||
$.cookie('one',tab);
|
||||
location.replace('/Dashboard/'+page+'?name='+disk);
|
||||
}
|
||||
|
||||
function capabilities(page,disk) {
|
||||
var tab = page=='New' ? 'tab3' : 'tab4';
|
||||
$.cookie('one',tab);
|
||||
location.replace('/Dashboard/'+page+'?name='+disk);
|
||||
}
|
||||
|
||||
function identity(page,disk) {
|
||||
var tab = page=='New' ? 'tab4' : 'tab5';
|
||||
$.cookie('one',tab);
|
||||
location.replace('/Dashboard/'+page+'?name='+disk);
|
||||
}
|
||||
|
||||
function acknowledge(id,disk) {
|
||||
$.post('/webGui/include/Acknowledge.php',{disk:disk},function(){
|
||||
$(id).removeClass('fa-thumbs-o-down orange-text').addClass('fa-thumbs-o-up green-text');$(id.replace('smart','text')).text("<?=_('healthy')?>");
|
||||
});
|
||||
}
|
||||
|
||||
function dropdown(menu) {
|
||||
var select = 'select[name="'+menu+'"]';
|
||||
var size = $(select+' option').length;
|
||||
var option = $.cookie(menu)||0;
|
||||
var option = cookie[menu]||0;
|
||||
if (option >= size) option = 0;
|
||||
$(select+' option')[option].selected = true;
|
||||
$(select).change();
|
||||
}
|
||||
|
||||
function toggleCPU(init) {
|
||||
if (!init) {if ($.cookie('cpu')==null) $.cookie('cpu','close',{expires:3650}); else $.removeCookie('cpu');}
|
||||
if ($.cookie('cpu')==null) {
|
||||
if (!init) {
|
||||
if (!cookie.cpu) cookie.cpu = 'close'; else delete cookie.cpu;
|
||||
saveCookie();
|
||||
}
|
||||
if (!cookie.cpu) {
|
||||
$('.cpu_open').show();
|
||||
$('.cpu_close').text("_(Hide details)_");
|
||||
} else {
|
||||
@@ -1110,13 +1163,17 @@ function toggleCPU(init) {
|
||||
}
|
||||
setTimeout(function(){toggleChart(true);});
|
||||
}
|
||||
|
||||
function toggleChart(init) {
|
||||
if (!init) {if ($.cookie('cpu-chart')==null) $.cookie('cpu-chart','close',{expires:3650}); else $.removeCookie('cpu-chart');}
|
||||
if (!init) {
|
||||
if (!cookie.cpu_chart) cookie.cpu_chart = 'close'; else delete cookie.cpu_chart;
|
||||
saveCookie();
|
||||
}
|
||||
$('#cpu_main').removeClass('last');
|
||||
$('.cpu_open:last').removeClass('last');
|
||||
if ($.cookie('cpu-chart')==null) {
|
||||
var hidden = $.cookie('hidden_content');
|
||||
hidden = hidden==null ? [] : hidden.split(';');
|
||||
if (!cookie.cpu_chart) {
|
||||
var hidden = cookie.hidden_content;
|
||||
hidden = hidden ? hidden.split(';') : [];
|
||||
if (hidden.indexOf($('#cpu_main').parent().attr('sort'))==-1) {
|
||||
$('#cpu_chart').show();
|
||||
$('#cpuline').show();
|
||||
@@ -1130,6 +1187,7 @@ function toggleChart(init) {
|
||||
if ($('.cpu_open').is(':visible')) $('.cpu_open:last').addClass('last'); else $('#cpu_main').addClass('last');
|
||||
}
|
||||
}
|
||||
|
||||
function StopArray() {
|
||||
<?if ($confirm['stop']):?>
|
||||
swal({title:"_(Proceed)_?",text:"_(This will stop the array)_",type:'warning',html:true,showCancelButton:true,confirmButtonText:"_(Proceed)_",cancelButtonText:"_(Cancel)_"},function(){StopArrayNow();});
|
||||
@@ -1137,10 +1195,12 @@ function StopArray() {
|
||||
StopArrayNow();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function StopArrayNow() {
|
||||
$('span.hand').prop('onclick',null).off('click').addClass('busy').css({'cursor':'default'});
|
||||
$.post('/update.htm',{startState:'<?=htmlspecialchars(_var($var,'mdState'))?>', cmdStop:'Stop'},function(){refresh();});
|
||||
}
|
||||
|
||||
function StartArray() {
|
||||
<?if ($confirm['stop']):?>
|
||||
swal({title:"_(Proceed)_?",text:"_(This will start the array)_",type:'warning',html:true,showCancelButton:true,confirmButtonText:"_(Proceed)_",cancelButtonText:"_(Cancel)_"},function(){StartArrayNow();});
|
||||
@@ -1148,10 +1208,12 @@ function StartArray() {
|
||||
StartArrayNow();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function StartArrayNow() {
|
||||
$('span.hand').prop('onclick',null).off('click').addClass('busy').css({'cursor':'default'});
|
||||
$.post('/update.htm',{startState:'<?=htmlspecialchars(_var($var,'mdState'))?>', cmdStart:'Start'},function(){refresh();});
|
||||
}
|
||||
|
||||
function Reboot() {
|
||||
<?if ($confirm['down']):?>
|
||||
swal({title:"_(Proceed)_?",text:"_(This will reboot the system)_",type:'warning',html:true,showCancelButton:true,confirmButtonText:"_(Proceed)_",cancelButtonText:"_(Cancel)_"},function(){RebootNow();});
|
||||
@@ -1159,10 +1221,12 @@ function Reboot() {
|
||||
RebootNow();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function RebootNow() {
|
||||
document.boot.cmd.value = 'reboot';
|
||||
document.boot.submit();
|
||||
}
|
||||
|
||||
function Shutdown() {
|
||||
<?if ($confirm['down']):?>
|
||||
swal({title:"_(Proceed)_?",text:"_(This will shutdown the system)_",type:'warning',html:true,showCancelButton:true,confirmButtonText:"_(Proceed)_",cancelButtonText:"_(Cancel)_"},function(){ShutdownNow();});
|
||||
@@ -1170,10 +1234,12 @@ function Shutdown() {
|
||||
ShutdownNow();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function ShutdownNow() {
|
||||
document.boot.cmd.value = 'shutdown';
|
||||
document.boot.submit();
|
||||
}
|
||||
|
||||
<?if ($sleep):?>
|
||||
function Sleep() {
|
||||
<?if ($confirm['sleep']):?>
|
||||
@@ -1182,16 +1248,17 @@ function Sleep() {
|
||||
SleepNow();
|
||||
<?endif;?>
|
||||
}
|
||||
|
||||
function SleepNow() {
|
||||
$('#statusraid').append(' • <span class="warning" style="font-weight:bold">System in sleep mode</span>');
|
||||
$.get('/plugins/dynamix.s3.sleep/include/SleepMode.php',function(){refresh();});
|
||||
}
|
||||
<?endif;?>
|
||||
|
||||
function sortTables() {
|
||||
$('table.dashboard').each(function(){
|
||||
var table = $(this);
|
||||
sanitizeMultiCookie(table.prop('id'), ';', true);
|
||||
var index = $.cookie(table.prop('id'));
|
||||
var index = cookie[table.prop('id')];
|
||||
// sorting list exists
|
||||
if (index != null) {
|
||||
index = index.split(';');
|
||||
@@ -1211,6 +1278,7 @@ function sortTables() {
|
||||
});
|
||||
$('table.dashboard tbody').before(stopgap);
|
||||
}
|
||||
|
||||
function addProperties() {
|
||||
$('div.frame tbody.system').addClass('sortable').attr('sort','_system_information_'.md5());
|
||||
$('div.frame tbody.system').find('td:first').prepend("<i class='fa fa-fw fa-eject control' onclick='openClose()' title=\"_(Show/Hide All Content)_\"></i>");
|
||||
@@ -1233,10 +1301,10 @@ function addProperties() {
|
||||
function(){if ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {recall.html(recover); recall=null;}}
|
||||
);
|
||||
}
|
||||
|
||||
function showContent() {
|
||||
var count = {'db-box1':$('table#db-box1 tbody').length, 'db-box2':$('table#db-box2 tbody').length, 'db-box3':$('table#db-box3 tbody').length}
|
||||
sanitizeMultiCookie('inactive_content', ';', true);
|
||||
var inactive = $.cookie('inactive_content');
|
||||
var count = {'db_box1':$('table#db_box1 tbody').length, 'db_box2':$('table#db_box2 tbody').length, 'db_box3':$('table#db_box3 tbody').length}
|
||||
var inactive = cookie.inactive_content;
|
||||
if (inactive) {
|
||||
inactive = inactive.split(';');
|
||||
for (let n=0,md5; md5=inactive[n]; n++) {
|
||||
@@ -1247,8 +1315,7 @@ function showContent() {
|
||||
tbody.prev().hide();
|
||||
}
|
||||
}
|
||||
sanitizeMultiCookie('hidden_content', ';', true);
|
||||
var hidden = $.cookie('hidden_content');
|
||||
var hidden = cookie.hidden_content;
|
||||
if (hidden) {
|
||||
hidden = hidden.split(';');
|
||||
for (let n=0,md5; md5=hidden[n]; n++) {
|
||||
@@ -1259,25 +1326,28 @@ function showContent() {
|
||||
tbody.find('span.button').hide();
|
||||
}
|
||||
}
|
||||
if (count['db-box1']>0) $('div#tile1').show();
|
||||
if (count['db-box2']>0) $('div#tile2').show();
|
||||
if (count['db-box3']>0) $('div#tile3').show();
|
||||
if (count['db_box1']>0) $('div#tile1').show();
|
||||
if (count['db_box2']>0) $('div#tile2').show();
|
||||
if (count['db_box3']>0) $('div#tile3').show();
|
||||
}
|
||||
|
||||
function setColor(l, t1, t2) {
|
||||
switch (true) {
|
||||
case (t1 > 0 && l >= t1): return 'redbar';
|
||||
case (t2 > 0 && l >= t2): return 'orangebar';
|
||||
default: return '';}
|
||||
}
|
||||
|
||||
function fontColor(l, t1, t2) {
|
||||
switch (true) {
|
||||
case (t1 > 0 && l >= t1): return '#f0000c';
|
||||
case (t2 > 0 && l >= t2): return '#e68a00';
|
||||
default: return '#4f8a10';}
|
||||
}
|
||||
|
||||
function openClose(button) {
|
||||
var hidden = $.cookie('hidden_content');
|
||||
hidden = hidden==null ? [] : hidden.split(';');
|
||||
var hidden = cookie.hidden_content;
|
||||
hidden = hidden ? hidden.split(';') : [];
|
||||
if (button) {
|
||||
// show/hide single tile content
|
||||
var tbody = button.closest('tbody');
|
||||
@@ -1290,7 +1360,7 @@ function openClose(button) {
|
||||
tbody.mixedView(1);
|
||||
hidden.splice(hidden.indexOf(tbody.attr('sort')),1);
|
||||
}
|
||||
$.cookie('hidden_content',hidden.join(';'),{expires:3650});
|
||||
cookie.hidden_content = hidden.join(';');
|
||||
} else {
|
||||
// show/hide all tiles content
|
||||
if (hidden.length==0) {
|
||||
@@ -1299,34 +1369,39 @@ function openClose(button) {
|
||||
$(this).mixedView(0);
|
||||
hidden.push($(this).attr('sort'));
|
||||
});
|
||||
$.cookie('hidden_content',hidden.join(';'),{expires:3650});
|
||||
cookie.hidden_content = hidden.join(';');
|
||||
} else {
|
||||
$('div.frame tbody').each(function(){
|
||||
$(this).find('.openclose').removeClass('fa-chevron-up fa-chevron-down').addClass('fa-chevron-up');
|
||||
$(this).mixedView(1);
|
||||
});
|
||||
$.removeCookie('hidden_content');
|
||||
delete cookie.hidden_content;
|
||||
}
|
||||
}
|
||||
saveCookie();
|
||||
}
|
||||
|
||||
function dismiss(button) {
|
||||
var tbody = button.closest('tbody');
|
||||
var table = tbody.parent();
|
||||
var tile = table.parent();
|
||||
var inactive = $.cookie('inactive_content');
|
||||
var inactive = cookie.inactive_content;
|
||||
tbody.hide();
|
||||
tbody.prev().hide();
|
||||
if (table.find('tbody:visible').length>0) tile.show(); else tile.hide();
|
||||
inactive = inactive==null ? [] : inactive.split(';');
|
||||
inactive = inactive ? inactive.split(';') : [];
|
||||
inactive.push(tbody.attr('sort'));
|
||||
$.cookie('inactive_content',inactive.join(';'),{expires:3650});
|
||||
cookie.inactive_content = inactive.join(';');
|
||||
saveCookie();
|
||||
}
|
||||
|
||||
function dialogStyle() {
|
||||
$('.ui-dialog-titlebar-close').css({'display':'none'});
|
||||
$('.ui-dialog-title').css({'text-align':'center','width':'100%','font-size':'1.8rem'});
|
||||
$('.ui-dialog-content').css({'padding-top':'15px','vertical-align':'bottom'});
|
||||
$('.ui-button-text').css({'padding':'0px 5px'});
|
||||
}
|
||||
|
||||
function contentMgmt() {
|
||||
box = $("#iframe-popup");
|
||||
box.html($("#templateContentMgmt").html().build());
|
||||
@@ -1338,11 +1413,12 @@ function contentMgmt() {
|
||||
modal: true,
|
||||
buttons: {
|
||||
"_(Reset)_": function(){
|
||||
$.removeCookie('db-box1');
|
||||
$.removeCookie('db-box2');
|
||||
$.removeCookie('db-box3');
|
||||
$.removeCookie('inactive_content');
|
||||
$.removeCookie('hidden_content');
|
||||
delete cookie.db_box1;
|
||||
delete cookie.db_box2;
|
||||
delete cookie.db_box3;
|
||||
delete cookie.inactive_content;
|
||||
delete cookie.hidden_content;
|
||||
saveCookie();
|
||||
box.dialog('close');
|
||||
location.reload();
|
||||
},
|
||||
@@ -1363,6 +1439,7 @@ function contentMgmt() {
|
||||
});
|
||||
dialogStyle();
|
||||
}
|
||||
|
||||
function VMClone(uuid, name){
|
||||
box = $("#iframe-popup");
|
||||
box.html($("#templateClone").html());
|
||||
@@ -1399,6 +1476,7 @@ function VMClone(uuid, name){
|
||||
});
|
||||
dialogStyle();
|
||||
}
|
||||
|
||||
function selectsnapshot(uuid, name ,snaps, opt, getlist, state,fstype){
|
||||
box = $("#iframe-popup");
|
||||
box.html($("#templatesnapshot"+opt).html());
|
||||
@@ -1486,7 +1564,7 @@ function LockButton() {
|
||||
$('i.tile').show();
|
||||
$('tbody.sortable').css({'cursor':'move'});
|
||||
$('div.nav-item.LockButton span').text("_(Lock sortable items)_");
|
||||
$('#db-box1,#db-box2,#db-box3').sortable({connectWith:'#db-box1,#db-box2,#db-box3'});
|
||||
$('#db_box1,#db_box2,#db_box3').sortable({connectWith:'#db_box1,#db_box2,#db_box3'});
|
||||
$('table.dashboard').sortable({helper:sortableHelper,items:'.sortable',cursor:'grab',opacity:0.6,placeholder:'dashboard-sortable',zIndex:9999,forceHelperSize:true,forcePlaceholderSize:true,
|
||||
receive:function(e,ui){
|
||||
var table = ui.sender, index = [];
|
||||
@@ -1500,13 +1578,14 @@ function LockButton() {
|
||||
gap.hide();
|
||||
}
|
||||
table.find('tbody').each(function(){index.push($(this).attr('sort'));});
|
||||
$.cookie(table.prop('id'),index.join(';'),{expires:3650});
|
||||
cookie[table.prop('id')] = index.join(';');
|
||||
},
|
||||
stop:function(e,ui){
|
||||
var table = ui.item.parent(), index = [];
|
||||
if (ui.item.prev().html().search('stopgap')>0) ui.item.after(stopgap); else ui.item.before(stopgap);
|
||||
table.find('tbody').each(function(){index.push($(this).attr('sort'));});
|
||||
$.cookie(table.prop('id'),index.join(';'),{expires:3650});
|
||||
cookie[table.prop('id')] = index.join(';');
|
||||
saveCookie();
|
||||
}});
|
||||
} else {
|
||||
$.removeCookie('lockbutton');
|
||||
@@ -1690,6 +1769,7 @@ dashboard.on('message',function(msg,meta) {
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
<?if ($apcupsd):?>
|
||||
var apcups = new NchanSubscriber('/sub/apcups',{subscriber:'websocket'});
|
||||
apcups.on('message',function(msg) {
|
||||
|
||||
@@ -4,8 +4,8 @@ Icon="icon-clock"
|
||||
Tag="clock-o"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -16,122 +16,308 @@ Tag="clock-o"
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$keys = explode("\n",file_get_contents("$docroot/webGui/include/timezones.key"));
|
||||
$validIP4 = "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$";
|
||||
$validIP6 = "^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(:|([0-9a-fA-F]{1,4}:)+):(([0-9a-fA-F]{1,4}:)*[0-9a-fA-F]{1,4})?)$";
|
||||
$validMAC = "^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$";
|
||||
$tmzones = file("$docroot/webGui/include/timezones.key",FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
|
||||
$system = "/sys/class/net";
|
||||
$hwclock = $ports = $member = [];
|
||||
|
||||
exec("ls --indicator-style=none $system|grep -P '^(bond|br|eth)[0-9]*$'",$net);
|
||||
foreach ($net as $port) {
|
||||
switch (preg_replace('/[0-9]+$/','',$port)) {
|
||||
case 'bond':
|
||||
if (!file_exists($system.'/'.str_replace('bond','br',$port))) $ports[] = $port;
|
||||
$member = array_merge($member,explode(' ',exec("cat $system/$port/bonding/slaves")));
|
||||
break;
|
||||
case 'br':
|
||||
$member = array_merge($member,explode(' ',exec("ls --indicator-style=none $system/$port/brif")));
|
||||
break;
|
||||
case 'eth':
|
||||
if (!in_array($port,$member)) $ports[] = $port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach ($ports as $port) $hwclock[$port] = exec("ethtool -T $port|grep -Pom1 '^PTP Hardware Clock: \K.+'")=='none' ? 'disabled' : '';
|
||||
?>
|
||||
<form markdown="1" name="datetime_settings" method="POST" action="/update.htm" target="progressFrame">
|
||||
<form markdown="1" name="datetime_settings" method="POST" action="/update.htm" target="progressFrame" onchange="signal(this)">
|
||||
<input type="hidden" name="setDateTime" value="apply">
|
||||
_(Current date and time)_:
|
||||
: <?=_(my_time(time()),0)?>
|
||||
|
||||
_(Date format)_:
|
||||
: <select name="display_date" onchange="presetTime(this.form)">
|
||||
<?=mk_option($display['date'], "%c","_(System Setting)_")?>
|
||||
<?=mk_option($display['date'], "%A, %Y %B %e",_('Day, YYYY Month D'))?>
|
||||
<?=mk_option($display['date'], "%A, %e %B %Y",_('Day, D Month YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %B %e, %Y",_('Day, Month D, YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %m/%d/%Y",_('Day, MM/DD/YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %d-%m-%Y",_('Day, DD-MM-YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %d.%m.%Y",_('Day, DD.MM.YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %Y-%m-%d",_('Day, YYYY-MM-DD'))?>
|
||||
<?=mk_option($display['date'], "%c", _('System Setting'))?>
|
||||
<?=mk_option($display['date'], "%A, %Y %B %e", _('Day, YYYY Month D'))?>
|
||||
<?=mk_option($display['date'], "%A, %e %B %Y", _('Day, D Month YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %B %e, %Y", _('Day, Month D, YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %m/%d/%Y", _('Day, MM/DD/YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %d-%m-%Y", _('Day, DD-MM-YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %d.%m.%Y", _('Day, DD.MM.YYYY'))?>
|
||||
<?=mk_option($display['date'], "%A, %Y-%m-%d", _('Day, YYYY-MM-DD'))?>
|
||||
</select>
|
||||
|
||||
_(Time format)_:
|
||||
: <select name="display_time">
|
||||
<?=mk_option($display['time'], "%I:%M %p",_('12 hours'))?>
|
||||
<?=mk_option($display['time'], "%R",_('24 hours'))?>
|
||||
<?=mk_option($display['time'], "%I:%M %p", _('12 hours'))?>
|
||||
<?=mk_option($display['time'], "%R", _('24 hours'))?>
|
||||
</select>
|
||||
|
||||
_(Time zone)_:
|
||||
: <select name="timeZone"><?
|
||||
foreach ($keys as $key) {
|
||||
[$timezone, $city] = my_explode('|', $key);
|
||||
foreach ($tmzones as $zone) {
|
||||
[$timezone, $city] = my_explode('|', $zone);
|
||||
echo mk_option($var['timeZone'], $timezone, $city);
|
||||
}
|
||||
?></select>
|
||||
|
||||
:timezone_help:
|
||||
|
||||
_(Use NTP)_:
|
||||
: <select name="USE_NTP" onchange="checkDateTimeSettings(this.form)">
|
||||
<?=mk_option($var['USE_NTP'], "yes", _('Yes'))?>
|
||||
<?=mk_option($var['USE_NTP'], "no", _('No'))?>
|
||||
_(Time state)_:
|
||||
: <span id="timeState"><i class="fa fa-spin fa-spinner"></i></span>
|
||||
|
||||
_(Time sync)_:
|
||||
: <select name="USE_NTP" onchange="updatePage(this.form,'slow')">
|
||||
<?=mk_option($var['USE_NTP'], "yes", _('NTP'))?>
|
||||
<?=mk_option($var['USE_NTP'], "yes", _('PTP'))?>
|
||||
<?=mk_option($var['USE_NTP'], "no", _('Manual'))?>
|
||||
</select>
|
||||
<span id="noports" class="red-text"><i class="fa fa-warning"></i> _(No suitable interfaces found for PTP)_</span>
|
||||
|
||||
:use_ntp_help:
|
||||
|
||||
<div markdown="1" id="ntp-setup" class="extra">
|
||||
_(NTP interval)_:
|
||||
: <select name="display_ntppoll">
|
||||
<?=mk_option(_var($display,'ntppoll'), "", _('Default'))?>
|
||||
<?=mk_option(_var($display,'ntppoll'), "8", _('Slow'))?>
|
||||
<?=mk_option(_var($display,'ntppoll'), "5", _('Medium'))?>
|
||||
<?=mk_option(_var($display,'ntppoll'), "3", _('Fast'))?>
|
||||
</select><span class="ntp orange-text">_(Use DEFAULT setting when public NTP servers are defined)_</span>
|
||||
: <select name="NTP_POLL">
|
||||
<?=mk_option(_var($NTP,'POLL'), "", _('Default'))?>
|
||||
<?=mk_option(_var($NTP,'POLL'), "8", _('Slow'))?>
|
||||
<?=mk_option(_var($NTP,'POLL'), "5", _('Medium'))?>
|
||||
<?=mk_option(_var($NTP,'POLL'), "3", _('Fast'))?>
|
||||
</select>
|
||||
<span class="orange-text">_(Use DEFAULT setting when public NTP servers are defined)_</span>
|
||||
|
||||
_(NTP server)_ 1:
|
||||
: <input type="text" name="NTP_SERVER1" maxlength="40" class="narrow" value="<?=htmlspecialchars($var['NTP_SERVER1'])?>">
|
||||
|
||||
:ntp_server1_help:
|
||||
<span class="orange-text">_(Input a NTP server name, NTP pool name or IP address)_</span>
|
||||
|
||||
_(NTP server)_ 2:
|
||||
: <input type="text" name="NTP_SERVER2" maxlength="40" class="narrow" value="<?=htmlspecialchars($var['NTP_SERVER2'])?>">
|
||||
|
||||
:ntp_server2_help:
|
||||
|
||||
_(NTP server)_ 3:
|
||||
: <input type="text" name="NTP_SERVER3" maxlength="40" class="narrow" value="<?=htmlspecialchars($var['NTP_SERVER3'])?>">
|
||||
|
||||
:ntp_server3_help:
|
||||
|
||||
_(NTP server)_ 4:
|
||||
: <input type="text" name="NTP_SERVER4" maxlength="40" class="narrow" value="<?=htmlspecialchars($var['NTP_SERVER4'])?>">
|
||||
|
||||
:ntp_server4_help:
|
||||
</div>
|
||||
<div markdown="1" id="ptp-setup" class="extra">
|
||||
_(PTP profile)_:
|
||||
: PTPv2 (IEEE 1588)
|
||||
|
||||
_(PTP transport)_:
|
||||
: <select name="PTP_TRANSPORT" onchange="updatePage(this.form,'slow')">
|
||||
<?=mk_option(_var($PTP,'TRANSPORT'), "UDPv4", _('UDPv4'))?>
|
||||
<?=mk_option(_var($PTP,'TRANSPORT'), "UDPv6", _('UDPv6'))?>
|
||||
<?=mk_option(_var($PTP,'TRANSPORT'), "L2", _('IEEE 802.3'))?>
|
||||
</select>
|
||||
|
||||
_(PTP mode)_:
|
||||
: <select name="PTP_MODE" onchange="updatePage(this.form,'slow')">
|
||||
<?=mk_option(_var($PTP,'MODE'), "multicast", _('Multicast'))?>
|
||||
<?=mk_option(_var($PTP,'MODE'), "unicast", _('Unicast'))?>
|
||||
</select>
|
||||
|
||||
<div markdown="1" id="unicast" class="extra">
|
||||
_(PTP server)_ 1:
|
||||
: <input type="text" name="PTP_SERVER1" maxlength="40" class="narrow" value="<?=htmlspecialchars(_var($PTP,'SERVER1'))?>">
|
||||
<span class="ipv4 orange-text">_(Input a IPv4 address)_</span><span class="ipv6 orange-text">_(Input a IPv6 address)_</span><span class="mac orange-text">_(Input a MAC address)_</span>
|
||||
|
||||
_(PTP server)_ 2:
|
||||
: <input type="text" name="PTP_SERVER2" maxlength="40" class="narrow" value="<?=htmlspecialchars(_var($PTP,'SERVER2'))?>">
|
||||
|
||||
_(PTP server)_ 3:
|
||||
: <input type="text" name="PTP_SERVER3" maxlength="40" class="narrow" value="<?=htmlspecialchars(_var($PTP,'SERVER3'))?>">
|
||||
|
||||
_(PTP server)_ 4:
|
||||
: <input type="text" name="PTP_SERVER4" maxlength="40" class="narrow" value="<?=htmlspecialchars(_var($PTP,'SERVER4'))?>">
|
||||
|
||||
</div>
|
||||
_(PTP interface)_:
|
||||
: <select name="PTP_PORT" onchange="hwclock(this.form,this.value)">
|
||||
<?if (empty($ports)) echo mk_option(0, '', '---');?>
|
||||
<?foreach($ports as $port):?>
|
||||
<?=mk_option(_var($PTP,'PORT','eth0'), $port, $port)?>
|
||||
<?endforeach;?>
|
||||
</select>
|
||||
|
||||
_(PTP clock)_:
|
||||
: <select name="PTP_CLOCK">
|
||||
<?=mk_option(_var($PTP,'CLOCK'), "hardware", _('Hardware'), empty($ports) ? 'disabled' : _var($hwclock,_var($PTP,'PORT')))?>
|
||||
<?=mk_option(_var($PTP,'CLOCK'), "software", _('Software'))?>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
<div markdown="1" id="manual-setup" class="extra">
|
||||
_(New date and time)_:
|
||||
: <input type="text" name="newDateTime" maxlength="20" class="narrow" value="<?=my_time(time(), "%F %T")?>">
|
||||
: <input type="text" name="newDateTime" maxlength="20" class="narrow" value="<?=my_time(time(),"%F %T")?>">
|
||||
<span class="orange-text">_(Input the correct date and time manually)_</span>
|
||||
|
||||
:current_time_help:
|
||||
|
||||
</div>
|
||||
|
||||
: <input type="button" value="_(Apply)_" onclick="doDispatch(this.form)" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
: <input type="button" value="_(Apply)_" onclick="dispatch(this.form)" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
function doDispatch(form) {
|
||||
var fields = {};
|
||||
var old_tz = "<?=$var['timeZone']?>";
|
||||
$(form).find('button').prop('disabled',true);
|
||||
fields['#cfg'] = "/boot/config/plugins/dynamix/dynamix.cfg";
|
||||
$(form).find('select[name^="display_"]').each(function(){fields[$(this).attr('name')] = $(this).val();});
|
||||
$.post('/webGui/include/Dispatcher.php',fields);
|
||||
if (form.timeZone.value != old_tz) $.post('/webGui/include/ResetTZ.php');
|
||||
form.submit();
|
||||
// update time service
|
||||
var service = false;
|
||||
var oldDate, oldTime, oldZone;
|
||||
|
||||
// ptp daemon is running?
|
||||
var ptpd = <?=exec("pgrep -cf /usr/sbin/ptp4l") ? 'true' : 'false'?>;
|
||||
|
||||
function hwclock(form,port) {
|
||||
// disable hardware clock if not supported
|
||||
var hwc = {};
|
||||
<?foreach ($hwclock as $port => $disabled):?>
|
||||
hwc.<?=$port?> = <?=$disabled ? 'true' : 'false'?>;
|
||||
<?endforeach;?>
|
||||
form.PTP_CLOCK.options[0].disabled = hwc[port];
|
||||
}
|
||||
|
||||
function signal(form) {
|
||||
if (service) return;
|
||||
if (form.display_date.selectedIndex != oldDate) {
|
||||
oldDate = form.display_date.selectedIndex;
|
||||
return;
|
||||
}
|
||||
if (form.display_time.selectedIndex != oldTime) {
|
||||
oldTime = form.display_time.selectedIndex;
|
||||
return
|
||||
}
|
||||
// time service needs update
|
||||
service = true;
|
||||
}
|
||||
|
||||
function disableButtons(state) {
|
||||
setTimeout(function(){$('input[type=button]').prop('disabled',state);});
|
||||
}
|
||||
|
||||
function dispatch(form) {
|
||||
var save = {};
|
||||
var valid = true;
|
||||
disableButtons(true);
|
||||
if (form.USE_NTP.selectedIndex==1 && form.PTP_MODE.selectedIndex==1) {
|
||||
let tr = form.PTP_TRANSPORT.value;
|
||||
let pattern = tr=='L2' ? /<?=$validMAC?>/ : (tr=='UDPv4' ? /<?=$validIP4?>/ : /<?=$validIP6?>/);
|
||||
// validate syntax of ptp server addresses
|
||||
$(form).find('input[name^="PTP_SERVER"]').each(function(){
|
||||
var text = $(this).val();
|
||||
if (text!='' && pattern.test(text)==false) valid = false;
|
||||
});
|
||||
} else if (form.USE_NTP.selectedIndex==1) {
|
||||
// clear ptp server addresses
|
||||
$('input[name^="PTP_SERVER"]').val('');
|
||||
}
|
||||
if (valid) {
|
||||
clearTimeout(timers.timeState);
|
||||
$('#timeState').html('<i class="fa fa-spin fa-spinner"></i>');
|
||||
let index = form.USE_NTP.selectedIndex;
|
||||
let cmd = index==1 ? (ptpd ? 'restart' : 'start') : 'stop';
|
||||
save['#cfg'] = "/boot/config/plugins/dynamix/dynamix.cfg";
|
||||
save.PTP_SYNC = index==1 ? 'yes' : 'no';
|
||||
$(form).find('select[name^="display_"],select[name="NTP_POLL"],select[name^="PTP_"],input[name^="display_"],input[name^="PTP_"]').each(function(){
|
||||
save[$(this).attr('name')] = $(this).val();
|
||||
// exclude setting for emhttpd
|
||||
$(this).prop('disabled',true);
|
||||
});
|
||||
// save dispatched variables
|
||||
$.post('/webGui/include/Dispatcher.php',save,function(){
|
||||
if (service) {
|
||||
// start/stop ptp daemon separately (emhttpd does not support it)
|
||||
$.post('/webGui/include/StartStopPTP.php',{cmd:cmd},function(){
|
||||
// reset timezone when it has changed
|
||||
if (form.timeZone.selectedIndex != oldZone) $.post('/webGui/include/ResetTZ.php');
|
||||
// start/stop ntp daemon (using emhttpd)
|
||||
form.submit();
|
||||
});
|
||||
} else {
|
||||
// no time service update needed
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
disableButtons(false);
|
||||
swal("_(Wrong PTP server address)_");
|
||||
}
|
||||
}
|
||||
|
||||
function presetTime(form) {
|
||||
var system = form.display_date.selectedIndex==0;
|
||||
if (system) form.display_time.selectedIndex = 0;
|
||||
form.display_time.disabled = system;
|
||||
}
|
||||
function checkDateTimeSettings(form) {
|
||||
if (form.USE_NTP.value=="yes") {
|
||||
|
||||
function updatePage(form,step) {
|
||||
if (form.USE_NTP.selectedIndex==0) {
|
||||
// ntp
|
||||
$('#ptp-setup,#manual-setup').hide(step);
|
||||
$('#ntp-setup').show(step);
|
||||
$('#noports').hide();
|
||||
form.newDateTime.disabled=true;
|
||||
form.display_ntppoll.disabled=false;
|
||||
form.NTP_SERVER1.disabled=false;
|
||||
form.NTP_SERVER2.disabled=false;
|
||||
form.NTP_SERVER3.disabled=false;
|
||||
form.NTP_SERVER4.disabled=false;
|
||||
} else if (form.USE_NTP.selectedIndex==1) {
|
||||
// ptp
|
||||
$('#ntp-setup,#manual-setup').hide(step);
|
||||
$('#ptp-setup').show(step);
|
||||
<?if (empty($ports)):?>
|
||||
$('#noports').show();
|
||||
<?else:?>
|
||||
$('#noports').hide();
|
||||
<?endif;?>
|
||||
if (form.PTP_MODE.selectedIndex==0) $('#unicast').hide(step); else $('#unicast').show(step);
|
||||
form.newDateTime.disabled=true;
|
||||
form.NTP_SERVER1.disabled=true;
|
||||
form.NTP_SERVER2.disabled=true;
|
||||
form.NTP_SERVER3.disabled=true;
|
||||
form.NTP_SERVER4.disabled=true;
|
||||
$('span.ipv4,span.ipv6,span.mac').hide();
|
||||
switch (form.PTP_TRANSPORT.selectedIndex) {
|
||||
case 0: $('span.ipv4').show(); break;
|
||||
case 1: $('span.ipv6').show(); break;
|
||||
case 2: $('span.mac').show(); break;
|
||||
}
|
||||
} else {
|
||||
// manual
|
||||
$('#ntp-setup,#ptp-setup').hide(step);
|
||||
$('#manual-setup').show(step);
|
||||
$('#noports').hide();
|
||||
form.newDateTime.disabled=false;
|
||||
form.display_ntppoll.disabled=true;
|
||||
form.NTP_SERVER1.disabled=true;
|
||||
form.NTP_SERVER2.disabled=true;
|
||||
form.NTP_SERVER3.disabled=true;
|
||||
form.NTP_SERVER4.disabled=true;
|
||||
}
|
||||
}
|
||||
|
||||
function timeState() {
|
||||
$.post('/webGui/include/DashboardApps.php',{ntp:'ntp'},function(ntp){$('#timeState').html(ntp);});
|
||||
timers.timeState = setTimeout(timeState,2000);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
var form = document.datetime_settings;
|
||||
presetTime(form);
|
||||
checkDateTimeSettings(form);
|
||||
oldDate = form.display_date.selectedIndex;
|
||||
oldTime = form.display_time.selectedIndex;
|
||||
oldZone = form.timeZone.selectedIndex;
|
||||
form.USE_NTP.selectedIndex = <?=_var($PTP,'SYNC')=='yes' ? 1 : ($var['USE_NTP']=='yes' ? 0 : 2)?>;
|
||||
<?if (empty($ports)):?>
|
||||
if (form.USE_NTP.selectedIndex==1) $('#noports').show();
|
||||
<?endif;?>
|
||||
updatePage(form);
|
||||
timeState();
|
||||
});
|
||||
</script>
|
||||
|
||||
+326
-324
File diff suppressed because it is too large
Load Diff
@@ -3,8 +3,8 @@ Title="_(Interface)_ ethX"
|
||||
Tag="icon-ethernet"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -41,37 +41,22 @@ if (strpos($locked,'bond')===0 || strpos($locked,'br')===0) {
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
function portcheck_ethX() {
|
||||
$.post('/webGui/include/CheckPort.php',{port:'ethX'},function(text) {
|
||||
var html = $('#user-notice').html();
|
||||
if (!html || html.indexOf('ethX')>0) showNotice(text);
|
||||
setTimeout(portcheck_ethX,10000);
|
||||
});
|
||||
}
|
||||
arg1.ethX = 'none';
|
||||
|
||||
$(function() {
|
||||
var ctrl = "<span id='wait_ethX' class='status vshift red-text' style='display:none;font-size:1.2rem;font-style:italic'><i class='fa fa-spinner fa-spin'></i> _(Please wait)_... _(configuring interface)_</span>";
|
||||
var form = document.ethX_settings;
|
||||
<?if ($tabbed && !$service):?>
|
||||
<?if (!$service):?>
|
||||
$('#tabX').bind({click:function(){
|
||||
$('#bond-ethX').dropdownchecklist('destroy').dropdownchecklist({emptyText:"_(None)_", width:<?=$width[0]?>});
|
||||
$('#bridge-ethX').dropdownchecklist('destroy').dropdownchecklist({emptyText:"_(None)_", width:<?=$width[0]?>});
|
||||
$('#bond-ethX').dropdownchecklist('destroy').dropdownchecklist({emptyText:"_(None)_", width:166});
|
||||
$('#bridge-ethX').dropdownchecklist('destroy').dropdownchecklist({emptyText:"_(None)_", width:166});
|
||||
}});
|
||||
<?endif;?>
|
||||
if (!$.cookie('#view-ethX')) {$('#view-ethX').show(); $('#tag-ethX').removeClass('fa-chevron-down').addClass('fa-chevron-up');}
|
||||
<?foreach ($vlan_ethX as $i):?>
|
||||
if (!$.cookie('#view-ethX-<?=$i?>')) {$('#view-ethX-<?=$i?>').show(); $('#tag-ethX-<?=$i?>').removeClass('fa-chevron-down').addClass('fa-chevron-up');}
|
||||
<?endforeach;?>
|
||||
$('#bond-ethX').dropdownchecklist({emptyText:"_(None)_", width:<?=$width[0]?>});
|
||||
$('#bridge-ethX').dropdownchecklist({emptyText:"_(None)_", width:<?=$width[0]?>});
|
||||
checkBondingSettings(form,0,'ethX');
|
||||
checkBridgingSettings(form,0,'ethX');
|
||||
checkNetworkAccess(form,'ethX');
|
||||
selectProtocol(form,'ethX');
|
||||
<?if (!$tabbed):?>
|
||||
$('div.title').each(function(){
|
||||
if ($(this).text().indexOf('Interface ethX')==0) $(this).find('span.left').append(ctrl);
|
||||
});
|
||||
<?endif;?>
|
||||
$('#bond-ethX').dropdownchecklist({emptyText:"_(None)_", width:166});
|
||||
$('#bridge-ethX').dropdownchecklist({emptyText:"_(None)_", width:166});
|
||||
checkBondingSettings(form,0);
|
||||
checkBridgingSettings(form,0);
|
||||
checkNetworkAccess(form);
|
||||
selectProtocol(form);
|
||||
<?if (isset($master_ethX)):?>
|
||||
$('div.slave-ethX').hide();
|
||||
disableForm(form);
|
||||
@@ -81,10 +66,13 @@ $(function() {
|
||||
<?if ($no_eth0):?>
|
||||
$('input[name="#shut_ethX"]').prop('disabled',true);
|
||||
<?endif;?>
|
||||
setTimeout(portcheck_ethX,Number('ethX'.substr(3))*1000);
|
||||
portcheck('ethX');
|
||||
presetRun(form);
|
||||
});
|
||||
</script>
|
||||
<form markdown="1" name="ethX_settings" method="POST" action="/update.php" target="progressFrame" onchange="doRun(this)" onsubmit="return prepareSettings(this)">
|
||||
|
||||
<div class="title nocontrol shift"> </div>
|
||||
<form markdown="1" name="ethX_settings" method="POST" action="/update.php" target="progressFrame" onchange="signalRun(this,2)" onsubmit="return prepareSettings(this)">
|
||||
<input type="hidden" name="#file" value="<?=$ini?>">
|
||||
<input type="hidden" name="#include" value="/webGui/include/update.ethernet.php">
|
||||
<input type="hidden" name="#section" value="ethX">
|
||||
@@ -96,16 +84,15 @@ $(function() {
|
||||
<input type="hidden" name="BRSTP" value="no">
|
||||
<input type="hidden" name="BRFD" value="0">
|
||||
_(Interface description)_:
|
||||
: <span class="status vshift"><i id="tag-ethX" class="fa fa-fw fa-chevron-down" style="cursor:pointer" onclick="viewToggle('ethX')"></i></span>
|
||||
<?if (!$more):?>
|
||||
<input type="text" name="DESCRIPTION:0" maxlength="80" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:0"))?>" oninput="noRun(this.form)">
|
||||
: <input type="text" name="DESCRIPTION:0" maxlength="80" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:0"))?>">
|
||||
<input type="button" class="form" value="_(Info)_" onclick="networkInfo('ethX')">
|
||||
<?else:?>
|
||||
<span class="<?=$class?>"><?=$reason?></span>
|
||||
: <span class="<?=$class?>"><?=$reason?></span>
|
||||
<?endif;?>
|
||||
|
||||
:eth_interface_description_help:
|
||||
|
||||
<div markdown="1" id="view-ethX" style="display:none">
|
||||
_(MAC address)_:
|
||||
: <?=strtoupper(exec("ip link show ethX|grep -Pom1 'ether \K\S+'"))?>
|
||||
|
||||
@@ -113,16 +100,16 @@ _(MAC address)_:
|
||||
|
||||
<div markdown="1" class="slave-ethX">
|
||||
_(Enable bonding)_:
|
||||
: <select name="BONDING" onchange="checkBondingSettings(this.form,1,'ethX')">
|
||||
: <select name="BONDING" onchange="checkBondingSettings(this.form,1)">
|
||||
<?=mk_option(_var($ethX,'BONDING'), "no", _("No"))?>
|
||||
<?=mk_option(_var($ethX,'BONDING'), "yes", _("Yes"))?>
|
||||
</select>
|
||||
|
||||
:eth_enable_bonding_help:
|
||||
|
||||
<div markdown="1" id="bond-members-ethX" style="display:none">
|
||||
<div markdown="1" id="bond-members-ethX" class="'hide">
|
||||
_(Bonding mode)_:
|
||||
: <select name="BONDING_MODE" onchange="checkBondingSettings(this.form,-1,'ethX')">
|
||||
: <select name="BONDING_MODE" onchange="checkBondingSettings(this.form,-1)">
|
||||
<?=mk_option(_var($ethX,'BONDING_MODE'), "0", _("balance-rr")." (0)")?>
|
||||
<?=mk_option(_var($ethX,'BONDING_MODE'), "1", _("active-backup")." (1)",isset($ethX['BONDING_MODE'])?'':'selected')?>
|
||||
<?=mk_option(_var($ethX,'BONDING_MODE'), "2", _("balance-xor")." (2)")?>
|
||||
@@ -131,12 +118,12 @@ _(Bonding mode)_:
|
||||
<?=mk_option(_var($ethX,'BONDING_MODE'), "5", _("balance-tlb")." (5)")?>
|
||||
<?=mk_option(_var($ethX,'BONDING_MODE'), "6", _("balance-alb")." (6)")?>
|
||||
</select>
|
||||
<span id="attention0" style="display:none">**_(Attention)_:** _(this mode requires a network switch with proper setup and support)_...</span>
|
||||
<span id="attention0" class="hide">**_(Attention)_:** _(this mode requires a network switch with proper setup and support)_...</span>
|
||||
|
||||
:eth_bonding_mode_help:
|
||||
|
||||
_(Bonding members of)_ bondX:
|
||||
: <select id="bond-ethX" name="BONDNICS" multiple="multiple" style="display:none">
|
||||
: <select id="bond-ethX" name="BONDNICS" multiple="multiple" class="'hide">
|
||||
<?=mk_option(_var($ethX,'BONDNICS'),'ethX','ethX','selected disabled')?>
|
||||
<?foreach ($ports as $port):?>
|
||||
<?if ($port!='ethX' && !locked('ethX',$port)) echo mk_option_check(_var($ethX,'BONDNICS'),$port,$port)?>
|
||||
@@ -147,16 +134,16 @@ _(Bonding members of)_ bondX:
|
||||
|
||||
</div>
|
||||
_(Enable bridging)_:
|
||||
: <select name="BRIDGING" onchange="checkBridgingSettings(this.form,1,'ethX')">
|
||||
: <select name="BRIDGING" onchange="checkBridgingSettings(this.form,1)">
|
||||
<?=mk_option(_var($ethX,'BRIDGING'), "no", _("No"))?>
|
||||
<?=mk_option(_var($ethX,'BRIDGING'), "yes", _("Yes"))?>
|
||||
</select>
|
||||
|
||||
:eth_enable_bridging_help:
|
||||
|
||||
<div markdown="1" id="bridge-members-ethX" style="display:none">
|
||||
<div markdown="1" id="bridge-members-ethX" class="'hide">
|
||||
_(Bridging members of)_ brX:
|
||||
: <select id="bridge-ethX" name="BRNICS" multiple="multiple" style="display:none">
|
||||
: <select id="bridge-ethX" name="BRNICS" multiple="multiple" class="'hide">
|
||||
<?=mk_option(_var($ethX,'BRNICS'),'ethX','ethX','selected disabled')?>
|
||||
<?foreach ($ports as $port):?>
|
||||
<?if ($port!='ethX' && !locked('ethX',$port)) echo mk_option_check(_var($ethX,'BRNICS'),$port,$port)?>
|
||||
@@ -167,7 +154,7 @@ _(Bridging members of)_ brX:
|
||||
|
||||
</div>
|
||||
_(Network protocol)_:
|
||||
: <select name="PROTOCOL:0" onchange="selectProtocol(this.form,'ethX',0)">
|
||||
: <select name="PROTOCOL:0" onchange="selectProtocol(this.form,0,'slow')">
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:0"), 'ipv4', _('IPv4 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:0"), 'ipv6', _('IPv6 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:0"), 'ipv4+ipv6', _('IPv4 + IPv6'))?>
|
||||
@@ -175,9 +162,9 @@ _(Network protocol)_:
|
||||
|
||||
:eth_network_protocol_help:
|
||||
|
||||
<div markdown="1" class="ipv4-ethX-0" style="display:none">
|
||||
<div markdown="1" class="ipv4-ethX-0 hide">
|
||||
_(IPv4 address assignment)_:
|
||||
: <select name="USE_DHCP:0" onchange="selectProtocol(this.form,'ethX',0)">
|
||||
: <select name="USE_DHCP:0" onchange="selectProtocol(this.form,0,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:0"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:0"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:0"), '', _('None'))?>
|
||||
@@ -185,40 +172,25 @@ _(IPv4 address assignment)_:
|
||||
|
||||
:eth_ipv4_address_assignment_help:
|
||||
|
||||
<div markdown="1" class="more-ipv4-ethX-0" style="display:none">
|
||||
<div markdown="1" class="more-ipv4-ethX-0 hide">
|
||||
_(IPv4 address)_:
|
||||
: <input type="text" name="IPADDR:0" maxlength="15" value="<?=_var($ethX,"IPADDR:0")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:0" class="slim">
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.0.0.0", "8")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.0.0", "16")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.128.0", "17")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.192.0", "18")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.224.0", "19")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.240.0", "20")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.248.0", "21")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.252.0", "22")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.254.0", "23")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.0", "24", _var($ethX,"IPADDR:0")?"":"selected")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.128", "25")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.192", "26")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.224", "27")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.240", "28")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.248", "29")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:0"), "255.255.255.252", "30")?>
|
||||
: <input type="text" name="IPADDR:0" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR:0")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:0" class="slim">
|
||||
<?foreach ($masks as $mask => $prefix) echo mk_option(_var($ethX,"NETMASK:0"), $mask, $prefix, _var($ethX,"NETMASK:0")=='' && $prefix=='24'?'selected':'');?>
|
||||
</select>
|
||||
|
||||
:eth_ipv4_address_help:
|
||||
|
||||
_(IPv4 default gateway)_:
|
||||
: <input type="text" name="GATEWAY:0" maxlength="15" value="<?=_var($ethX,"GATEWAY:0")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:0" min="0" max="9999" value="<?=_var($ethX,"METRIC:0")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY:0" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY:0")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:0" min="0" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC:0")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
:eth_ipv4_default_gateway_help:
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div markdown="1" class="ipv6-ethX-0" style="display:none">
|
||||
<div markdown="1" class="ipv6-ethX-0 hide">
|
||||
_(IPv6 address assignment)_:
|
||||
: <select name="USE_DHCP6:0" onchange="selectProtocol(this.form,'ethX',0)">
|
||||
: <select name="USE_DHCP6:0" onchange="selectProtocol(this.form,0,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:0"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:0"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:0"), '', _('None'))?>
|
||||
@@ -226,18 +198,20 @@ _(IPv6 address assignment)_:
|
||||
|
||||
:eth_ipv6_address_assignment_help:
|
||||
|
||||
<div markdown="1" class="more-ipv6-ethX-0" style="display:none">
|
||||
<div markdown="1" class="more-ipv6-ethX-0 hide">
|
||||
_(IPv6 address)_:
|
||||
: <input type="text" name="IPADDR6:0" maxlength="39" value="<?=_var($ethX,"IPADDR6:0")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:0" min="1" max="128" value="<?=_var($ethX,"NETMASK6:0")?>" class="slim">
|
||||
: <input type="text" name="IPADDR6:0" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR6:0")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:0" min="1" max="128" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"NETMASK6:0")?>" class="slim">
|
||||
|
||||
:eth_ipv6_address_help:
|
||||
|
||||
_(IPv6 default gateway)_:
|
||||
: <input type="text" name="GATEWAY6:0" maxlength="39" value="<?=_var($ethX,"GATEWAY6:0")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:0" min="0" max="9999" value="<?=_var($ethX,"METRIC6:0")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY6:0" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY6:0")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:0" min="0" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC6:0")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
:eth_ipv6_default_gateway_help:
|
||||
|
||||
</div>
|
||||
<div markdown="1" class="priv-ipv6-ethX-0 hide">
|
||||
_(IPv6 privacy extensions)_:
|
||||
: <select name="PRIVACY6:0">
|
||||
<?=mk_option(_var($ethX,"PRIVACY6:0"), "0", _("Disabled"))?>
|
||||
@@ -249,38 +223,38 @@ _(IPv6 privacy extensions)_:
|
||||
</div>
|
||||
</div>
|
||||
_(Desired MTU)_:
|
||||
: <input type="number" name="MTU" min="68" max="9198" value="<?=_var($ethX,'MTU')?>" class="narrow" placeholder="1500">
|
||||
: <input type="number" name="MTU" min="68" max="9198" autocomplete="off" spellcheck="false" value="<?=_var($ethX,'MTU')?>" class="narrow" placeholder="1500">
|
||||
|
||||
:eth_desired_mtu_help:
|
||||
|
||||
_(Enable VLANs)_:
|
||||
: <select name="TYPE" onchange="checkNetworkAccess(this.form,'ethX')">
|
||||
: <select name="TYPE" onchange="checkNetworkAccess(this.form)">
|
||||
<?=mk_option(_var($ethX,'TYPE'), 'access', _('No'))?>
|
||||
<?=mk_option(_var($ethX,'TYPE'), 'trunk', _('Yes'))?>
|
||||
</select>
|
||||
<input type="button" id="button-vlan-ethX" class="form hide" value="_(Show)_" onclick="showVLAN('ethX')">
|
||||
|
||||
:eth_enable_vlans_help:
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id='index-ethX-0'></div>
|
||||
<div id="vlan-list-ethX" class="hide">
|
||||
<?foreach ($vlan_ethX as $i):?>
|
||||
<div markdown="1" id="index-ethX-<?=$i?>" class="access-ethX shade-<?=$display['theme']?>" style="display:none">
|
||||
<div markdown="1" id="index-ethX-<?=$i?>" class="access-ethX shade-<?=$display['theme']?> hide">
|
||||
_(Interface description)_:
|
||||
: <span class="status vshift"><i id="tag-ethX-<?=$i?>" class="fa fa-fw fa-chevron-down" style="cursor:pointer" onclick="viewToggle('ethX','<?=$i?>')"></i></span>
|
||||
<input type="text" name="DESCRIPTION:<?=$i?>" maxlength="80" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:$i"))?>" oninput="noRun(this.form)">
|
||||
: <input type="text" name="DESCRIPTION:<?=$i?>" maxlength="80" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:$i"))?>">
|
||||
<input type="button" class="form" value="_(Info)_" onclick="networkInfo('eth0',<?=_var($ethX,"VLANID:$i")?>)">
|
||||
|
||||
:eth_interface_description_help:
|
||||
|
||||
<div markdown="1" id="view-ethX-<?=$i?>" style="display:none">
|
||||
_(VLAN number)_:
|
||||
: <input type="number" name="VLANID:<?=$i?>" min="1" max="4095" value="<?=_var($ethX,"VLANID:$i")?>" class="narrow gap" required>
|
||||
: <input type="number" name="VLANID:<?=$i?>" min="1" max="4095" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"VLANID:$i")?>" class="narrow gap" required>
|
||||
<?if (!$service):?><input type="button" class="form" value="_(Delete VLAN)_" onclick="removeVLAN($('#index-ethX-<?=$i?>'))"><?endif;?>
|
||||
|
||||
:eth_vlan_number_help:
|
||||
|
||||
_(Network protocol)_:
|
||||
: <select name="PROTOCOL:<?=$i?>" onchange="selectProtocol(this.form,'ethX',<?=$i?>)">
|
||||
: <select name="PROTOCOL:<?=$i?>" onchange="selectProtocol(this.form,<?=$i?>,'slow')">
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:$i"), 'ipv4', _('IPv4 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:$i"), 'ipv6', _('IPv6 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:$i"), 'ipv4+ipv6', _('IPv4 + IPv6'))?>
|
||||
@@ -288,9 +262,9 @@ _(Network protocol)_:
|
||||
|
||||
:eth_network_protocol_help:
|
||||
|
||||
<div markdown="1" class="ipv4-ethX-<?=$i?>" style="display:none">
|
||||
<div markdown="1" class="ipv4-ethX-<?=$i?> hide">
|
||||
_(IPv4 address assignment)_:
|
||||
: <select name="USE_DHCP:<?=$i?>" onchange="selectProtocol(this.form,'ethX',<?=$i?>)">
|
||||
: <select name="USE_DHCP:<?=$i?>" onchange="selectProtocol(this.form,<?=$i?>,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:$i"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:$i"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:$i"), '', _('None'))?>
|
||||
@@ -298,40 +272,25 @@ _(IPv4 address assignment)_:
|
||||
|
||||
:eth_ipv4_address_assignment_help:
|
||||
|
||||
<div markdown="1" class="more-ipv4-ethX-<?=$i?>" style="display:none">
|
||||
<div markdown="1" class="more-ipv4-ethX-<?=$i?> hide">
|
||||
_(IPv4 address)_:
|
||||
: <input type="text" name="IPADDR:<?=$i?>" maxlength="15" value="<?=_var($ethX,"IPADDR:$i")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:<?=$i?>" class="slim">
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.0.0.0", "8")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.0.0", "16")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.128.0", "17")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.192.0", "18")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.224.0", "19")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.240.0", "20")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.248.0", "21")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.252.0", "22")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.254.0", "23")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.0", "24", isset($ethX["IPADDR:$i"])?"":"selected")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.128", "25")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.192", "26")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.224", "27")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.240", "28")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.248", "29")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:$i"), "255.255.255.252", "30")?>
|
||||
: <input type="text" name="IPADDR:<?=$i?>" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR:$i")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:<?=$i?>" class="slim">
|
||||
<?foreach ($masks as $mask => $prefix) echo mk_option(_var($ethX,"NETMASK:$i"), $mask, $prefix, _var($ethX,"NETMASK:$i")=='' && $prefix=='24'?'selected':'');?>
|
||||
</select>
|
||||
|
||||
:eth_ipv4_address_help:
|
||||
|
||||
_(IPv4 default gateway)_:
|
||||
: <input type="text" name="GATEWAY:<?=$i?>" maxlength="15" value="<?=_var($ethX,"GATEWAY:$i")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:<?=$i?>" min="0" max="9999" value="<?=_var($ethX,"METRIC:$i")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY:<?=$i?>" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY:$i")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:<?=$i?>" min="0" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC:$i")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
:eth_ipv4_default_gateway_help:
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div markdown="1" class="ipv6-ethX-<?=$i?>" style="display:none">
|
||||
<div markdown="1" class="ipv6-ethX-<?=$i?> hide">
|
||||
_(IPv6 address assignment)_:
|
||||
: <select name="USE_DHCP6:<?=$i?>" onchange="selectProtocol(this.form,'ethX',<?=$i?>)">
|
||||
: <select name="USE_DHCP6:<?=$i?>" onchange="selectProtocol(this.form,<?=$i?>,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:$i"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:$i"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:$i"), '', _('None'))?>
|
||||
@@ -339,18 +298,20 @@ _(IPv6 address assignment)_:
|
||||
|
||||
:eth_ipv6_address_assignment_help:
|
||||
|
||||
<div markdown="1" class="more-ipv6-ethX-<?=$i?>" style="display:none">
|
||||
<div markdown="1" class="more-ipv6-ethX-<?=$i?> hide">
|
||||
_(IPv6 address)_:
|
||||
: <input type="text" name="IPADDR6:<?=$i?>" maxlength="39" value="<?=_var($ethX,"IPADDR6:$i")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:<?=$i?>" min="1" max="128" value="<?=_var($ethX,"NETMASK6:$i")?>" class="slim">
|
||||
: <input type="text" name="IPADDR6:<?=$i?>" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR6:$i")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:<?=$i?>" min="1" max="128" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"NETMASK6:$i")?>" class="slim">
|
||||
|
||||
:eth_ipv6_address_help:
|
||||
|
||||
_(IPv6 default gateway)_:
|
||||
: <input type="text" name="GATEWAY6:<?=$i?>" maxlength="39" value="<?=_var($ethX,"GATEWAY6:$i")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:<?=$i?>" min="0" max="9999" value="<?=_var($ethX,"METRIC6:$i")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY6:<?=$i?>" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY6:$i")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:<?=$i?>" min="0" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC6:$i")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
:eth_ipv6_default_gateway_help:
|
||||
|
||||
</div>
|
||||
<div markdown="1" class="priv-ipv6-ethX-<?=$i?> hide">
|
||||
_(IPv6 privacy extensions)_:
|
||||
: <select name="PRIVACY6:<?=$i?>">
|
||||
<?=mk_option(_var($ethX,"PRIVACY6:$i"), "0", _("Disabled"))?>
|
||||
@@ -362,86 +323,71 @@ _(IPv6 privacy extensions)_:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?endforeach;?>
|
||||
</div>
|
||||
|
||||
|
||||
: <input type="submit" value="_(Apply)_" onclick="$('#wait_<?=$tabbed?'eth0':'ethX'?>').show()" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
<input type="button" name="#shut_ethX" value="<?=_('Port '.$cmd)?>" onclick="portToggle('ethX','<?=$cmd?>')">
|
||||
<?if (!$service):?>
|
||||
<input type="button" class="access-ethX" value="_(Add VLAN)_" onclick="addVLAN('ethX')" style="display:none">
|
||||
<input type="button" id="button-add-ethX" class="hide" value="_(Add VLAN)_" onclick="addVLAN('ethX')">
|
||||
<?else:?><?=sprintf(_('Stop **%s** to make changes, see'),$service).' (<a href="/Settings">'._('Settings').'</a>)'?><?endif;?>
|
||||
</form>
|
||||
|
||||
<script markdown="1" type="text/html" id="network-template-ethX">
|
||||
<div markdown="1" id="index-ethX-INDEX" class="access-ethX shade-<?=$display['theme']?>">
|
||||
_(Interface description)_:
|
||||
: <span class="status vshift"><i id="tag-ethX-INDEX" class="fa fa-fw fa-chevron-up" style="cursor:pointer" onclick="viewToggle('ethX','INDEX')"></i></span>
|
||||
<input type="text" name="DESCRIPTION:INDEX" maxlength="80" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:INDEX"))?>" oninput="noRun(this.form)">
|
||||
: <input type="text" name="DESCRIPTION:INDEX" maxlength="80" autocomplete="off" spellcheck="false" value="<?=htmlspecialchars(_var($ethX,"DESCRIPTION:INDEX"))?>">
|
||||
|
||||
<div markdown="1" id="view-ethX-INDEX">
|
||||
_(VLAN number)_:
|
||||
: <input type="number" name="VLANID:INDEX" min="1" max="4095" value="<?=_var($ethX,"VLANID:INDEX")?>" class="narrow gap" required>
|
||||
: <input type="number" name="VLANID:INDEX" min="1" max="4095" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"VLANID:INDEX")?>" class="narrow gap" required>
|
||||
<input type="button" class="form" value="_(Delete VLAN)_" onclick="removeVLAN($('#index-ethX-INDEX'))">
|
||||
|
||||
_(Network protocol)_:
|
||||
: <select name="PROTOCOL:INDEX" onchange="selectProtocol(this.form,'ethX',INDEX)">
|
||||
: <select name="PROTOCOL:INDEX" onchange="selectProtocol(this.form,INDEX,'slow')">
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:INDEX"), 'ipv4', _('IPv4 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:INDEX"), 'ipv6', _('IPv6 only'))?>
|
||||
<?=mk_option(_var($ethX,"PROTOCOL:INDEX"), 'ipv4+ipv6', _('IPv4 + IPv6'))?>
|
||||
</select>
|
||||
|
||||
<div markdown="1" class="ipv4-ethX-INDEX" style="display:none">
|
||||
<div markdown="1" class="ipv4-ethX-INDEX">
|
||||
_(IPv4 address assignment)_:
|
||||
: <select name="USE_DHCP:INDEX" onchange="selectProtocol(this.form,'ethX',INDEX)">
|
||||
: <select name="USE_DHCP:INDEX" onchange="selectProtocol(this.form,INDEX,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:INDEX"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:INDEX"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP:INDEX"), '', _('None'))?>
|
||||
</select>
|
||||
|
||||
<div markdown="1" class="more-ipv4-ethX-INDEX" style="display:none">
|
||||
<div markdown="1" class="more-ipv4-ethX-INDEX hide">
|
||||
_(IPv4 address)_:
|
||||
: <input type="text" name="IPADDR:INDEX" maxlength="15" value="<?=_var($ethX,"IPADDR:INDEX")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:INDEX" class="slim">
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.0.0.0", "8")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.0.0", "16")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.128.0", "17")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.192.0", "18")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.224.0", "19")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.240.0", "20")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.248.0", "21")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.252.0", "22")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.254.0", "23")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.0", "24", "selected")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.128", "25")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.192", "26")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.224", "27")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.240", "28")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.248", "29")?>
|
||||
<?=mk_option(_var($ethX,"NETMASK:INDEX"), "255.255.255.252", "30")?>
|
||||
: <input type="text" name="IPADDR:INDEX" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR:INDEX")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">/<select name="NETMASK:INDEX" class="slim">
|
||||
<?foreach ($masks as $mask => $prefix) echo mk_option(_var($ethX,"NETMASK:INDEX"), $mask, $prefix, $prefix=='24'?'selected':'');?>
|
||||
</select>
|
||||
|
||||
_(IPv4 default gateway)_:
|
||||
: <input type="text" name="GATEWAY:INDEX" maxlength="15" value="<?=_var($ethX,"GATEWAY:INDEX")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:INDEX" min="1" max="9999" value="<?=_var($ethX,"METRIC:INDEX")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY:INDEX" maxlength="15" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY:INDEX")?>" class="narrow" pattern="<?=$validIP4?>" title="_(IPv4 address A.B.C.D)_">
|
||||
<input type="text" name="METRIC:INDEX" min="1" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC:INDEX")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div markdown="1" class="ipv6-ethX-INDEX" style="display:none">
|
||||
<div markdown="1" class="ipv6-ethX-INDEX hide">
|
||||
_(IPv6 address assignment)_:
|
||||
: <select name="USE_DHCP6:INDEX" onchange="selectProtocol(this.form,'ethX',INDEX)">
|
||||
: <select name="USE_DHCP6:INDEX" onchange="selectProtocol(this.form,INDEX,'slow')">
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:INDEX"), 'yes', _('Automatic'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:INDEX"), 'no', _('Static'))?>
|
||||
<?=mk_option(_var($ethX,"USE_DHCP6:INDEX"), '', _('None'))?>
|
||||
</select>
|
||||
|
||||
<div markdown="1" class="more-ipv6-ethX-INDEX" style="display:none">
|
||||
<div markdown="1" class="more-ipv6-ethX-INDEX hide">
|
||||
_(IPv6 address)_:
|
||||
: <input type="text" name="IPADDR6:INDEX" maxlength="39" value="<?=_var($ethX,"IPADDR6:INDEX")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:INDEX" min="1" max="128" value="<?=_var($ethX,"NETMASK6:INDEX")?>" class="slim">
|
||||
: <input type="text" name="IPADDR6:INDEX" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"IPADDR6:INDEX")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">/<input type="number" name="NETMASK6:INDEX" min="1" max="128" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"NETMASK6:INDEX")?>" class="slim">
|
||||
|
||||
_(IPv6 default gateway)_:
|
||||
: <input type="text" name="GATEWAY6:INDEX" maxlength="39" value="<?=_var($ethX,"GATEWAY6:INDEX")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:INDEX" min="1" max="9999" value="<?=_var($ethX,"METRIC6:INDEX")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
: <input type="text" name="GATEWAY6:INDEX" maxlength="39" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"GATEWAY6:INDEX")?>" pattern="<?=$validIP6?>" title="_(IPv6 address nnnn:xxxx::yyyy)_">
|
||||
<input type="text" name="METRIC6:INDEX" min="1" max="9999" autocomplete="off" spellcheck="false" value="<?=_var($ethX,"METRIC6:INDEX")?>" class="slim"><i class="fa fa-sort-numeric-asc"></i> *_(optional metric (lowest is preferred, 0 is no default gateway))_*
|
||||
|
||||
</div>
|
||||
<div markdown="1" class="priv-ipv6-ethX-INDEX hide">
|
||||
_(IPv6 privacy extensions)_:
|
||||
: <select name="PRIVACY6:INDEX">
|
||||
<?=mk_option(_var($ethX,'PRIVACY6:INDEX'), "0", _("Disabled"))?>
|
||||
@@ -451,5 +397,4 @@ _(IPv6 privacy extensions)_:
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Menu="NetworkSettings"
|
||||
Title="Interface Extra"
|
||||
Tag="icon-ethernet"
|
||||
Tag="icon-custom"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2023, Lime Technology
|
||||
* Copyright 2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -28,7 +28,7 @@ if (file_exists($cfg)) {
|
||||
?>
|
||||
<script>
|
||||
function prepareText(form) {
|
||||
var mgmt = ['br0','bond0','eth0'];
|
||||
var mgmt = ['br0','bond0','eth0','wlan0'];
|
||||
form.include_interfaces.value = form.include.value.replace(/[\n,]/g,' ').replace(/ +/g,' ').trim();
|
||||
form.exclude_interfaces.value = form.exclude.value.replace(/[\n,]/g,' ').replace(/ +/g,' ').trim();
|
||||
form.include.disabled = true;
|
||||
@@ -52,36 +52,15 @@ function prepareText(form) {
|
||||
return true;
|
||||
}
|
||||
|
||||
<?if (!$tabbed):?>
|
||||
function toggleExtra() {
|
||||
var tag = '#tag_extra';
|
||||
var view = '#extra_table';
|
||||
if ($(view).is(':visible')) {
|
||||
$(tag).removeClass('fa-chevron-up').addClass('fa-chevron-down');
|
||||
$.cookie(view,'hide',{expires:3650});
|
||||
} else {
|
||||
$(tag).removeClass('fa-chevron-down').addClass('fa-chevron-up');
|
||||
$.removeCookie(view);
|
||||
}
|
||||
$(view).toggle('slow');
|
||||
}
|
||||
$(function(){
|
||||
$('div.title').eq(-3).find('span.left').append("<span class='status vhshift'><i id='tag_extra' class='fa fa-fw fa-chevron-up' style='cursor:pointer' onclick='toggleExtra()'></i></span>");
|
||||
if (!$.cookie('#extra_table')) $('#extra_table').show(); else {$('#extra_table').hide(); $('#tag_extra').removeClass('fa-chevron-up').addClass('fa-chevron-down');}
|
||||
});
|
||||
<?else:?>
|
||||
$(function(){
|
||||
$('#extra_table').show();
|
||||
});
|
||||
<?endif;?>
|
||||
$(function(){
|
||||
$('form textarea').on('input',function(){
|
||||
$(this).prop('rows',($(this).val().match(/\n/g)||[]).length+1);
|
||||
});
|
||||
setInterval(function(){$.post('/webGui/include/NetworkInfo.php',{listen:'listen'},function(text) {$('#listen').html(text);});},5000);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div markdown="1" id="extra_table" style="display:none">
|
||||
<div class="title nocontrol shift"> </div>
|
||||
<form markdown="1" name="network_extra" method="POST" action="/update.php" target="progressFrame" onsubmit="return prepareText(this)">
|
||||
<input type="hidden" name="#file" value="<?=$cfg?>">
|
||||
<input type="hidden" name="#command" value="/webGui/scripts/reload_services">
|
||||
@@ -89,7 +68,7 @@ $(function(){
|
||||
<input type="hidden" name="exclude_interfaces" value="">
|
||||
|
||||
_(Current listening interfaces)_:
|
||||
: <?=exec("$docroot/webGui/scripts/show_interfaces")?:_('Any')?><span class="red-text" style="margin-left:30px"><?=exec("$docroot/webGui/scripts/error_interfaces")?></span>
|
||||
: <span id="listen"><?=exec("$docroot/webGui/scripts/show_interfaces")?:_('Any')?></span><span class="red-text" style="margin-left:30px"><?=exec("$docroot/webGui/scripts/error_interfaces")?></span>
|
||||
<hr>
|
||||
|
||||
_(Include listening interfaces)_:
|
||||
@@ -105,5 +84,3 @@ _(Exclude listening interfaces)_:
|
||||
|
||||
: <input type="submit" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -4,8 +4,8 @@ Tag="icon-network"
|
||||
Cond="file_exists('/boot/config/network-rules.cfg')"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2023, Lime Technology
|
||||
* Copyright 2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -53,30 +53,8 @@ function check_rules(form) {
|
||||
function update_info(id,mac) {
|
||||
$('#info-'+id).html(info['_'+mac.replace(/:/g,'')]);
|
||||
}
|
||||
<?if (!$tabbed):?>
|
||||
function toggleRules() {
|
||||
var tag = '#tag_rules';
|
||||
var view = '#rules_table';
|
||||
if ($(view).is(':visible')) {
|
||||
$(tag).removeClass('fa-chevron-up').addClass('fa-chevron-down');
|
||||
$.cookie(view,'hide',{expires:3650});
|
||||
} else {
|
||||
$(tag).removeClass('fa-chevron-down').addClass('fa-chevron-up');
|
||||
$.removeCookie(view);
|
||||
}
|
||||
$(view).toggle('slow');
|
||||
}
|
||||
$(function(){
|
||||
$('div.title').eq(-2).find('span.left').append("<span class='status vhshift'><i id='tag_rules' class='fa fa-fw fa-chevron-up' style='cursor:pointer' onclick='toggleRules()'></i></span>");
|
||||
if (!$.cookie('#rules_table')) $('#rules_table').show(); else {$('#rules_table').hide(); $('#tag_rules').removeClass('fa-chevron-up').addClass('fa-chevron-down');}
|
||||
});
|
||||
<?else:?>
|
||||
$(function(){
|
||||
$('#rules_table').show();
|
||||
});
|
||||
<?endif;?>
|
||||
</script>
|
||||
<div markdown="1" id="rules_table" style="display:none">
|
||||
<div class="title nocontrol shift"> </div>
|
||||
<form markdown="1" name="network_rules" method="POST" action="/update.php" target="progressFrame" onsubmit="return check_rules(this)">
|
||||
<input type="hidden" name="#file" value="not-used">
|
||||
<input type="hidden" name="#include" value="/webGui/include/update.rules.php">
|
||||
@@ -101,4 +79,3 @@ _(Interface)_ <?=$eth?>:
|
||||
<?if (file_exists('/tmp/network-rules.tmp')):?>
|
||||
<br><span class="error" style="text-align:center;padding:12px 0">_(Please **Reboot** system to make new rules active)_</span>
|
||||
<?endif;?>
|
||||
</div>
|
||||
|
||||
@@ -2,3 +2,4 @@ Menu="OtherSettings"
|
||||
Type="xmenu"
|
||||
Title="Network Settings"
|
||||
Icon="icon-network"
|
||||
Tabs="true"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
Menu="Scheduler:1"
|
||||
Title="Parity Check"
|
||||
Tag="calendar"
|
||||
Cond="$disks['parity']['device'] || $disks['parity2']['device']"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2012-2023, Bergware International.
|
||||
* Copyright 2005-2023, Lime Technology
|
||||
/* Copyright 2012-2025, Bergware International.
|
||||
* Copyright 2005-2025, Lime Technology
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -18,6 +19,7 @@ Tag="calendar"
|
||||
if (_var($disks['parity'],'status')=='DISK_NP_DSBL' && _var($disks['parity2'],'status')=='DISK_NP_DSBL') {
|
||||
echo "<p class='notice'>"._('No Parity disk present')."!</p>";
|
||||
}
|
||||
|
||||
$width = [166,300];
|
||||
$mode = ['Disabled','Daily','Weekly','Monthly','Yearly','Custom'];
|
||||
$days = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
|
||||
|
||||
@@ -3,8 +3,8 @@ Title="Routing Table"
|
||||
Tag="icon-share"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -48,32 +48,10 @@ function resetTable() {
|
||||
clearTimeout(timers.routeTable);
|
||||
routeTable();
|
||||
}
|
||||
<?if (!$tabbed):?>
|
||||
function toggleTable() {
|
||||
var tag = '#tag_table';
|
||||
var view = '#route_table';
|
||||
if ($(view).is(':visible')) {
|
||||
$(tag).removeClass('fa-chevron-up').addClass('fa-chevron-down');
|
||||
$.cookie(view,'hide',{expires:3650});
|
||||
} else {
|
||||
$(tag).removeClass('fa-chevron-down').addClass('fa-chevron-up');
|
||||
$.removeCookie(view);
|
||||
}
|
||||
$(view).toggle('slow');
|
||||
}
|
||||
$(function(){
|
||||
$('div.title').last().find('span.left').append("<span class='status vhshift'><i id='tag_table' class='fa fa-fw fa-chevron-up' style='cursor:pointer' onclick='toggleTable()'></i></span>");
|
||||
if (!$.cookie('#route_table')) $('#route_table').show(); else $('#tag_table').removeClass('fa-chevron-up').addClass('fa-chevron-down');
|
||||
routeTable();
|
||||
});
|
||||
<?else:?>
|
||||
$(function(){
|
||||
$('#route_table').show();
|
||||
routeTable();
|
||||
});
|
||||
<?endif;?>
|
||||
</script>
|
||||
<div markdown="1" id="route_table" style="display:none">
|
||||
<table class="unraid">
|
||||
<thead><tr><td>_(Protocol)_</td><td>_(Route)_</td><td>_(Gateway)_</td><td>_(Metric)_</td><td style="width:8%;text-align:center">_(Delete)_</td></tr></thead>
|
||||
<tbody id="route_list"></tbody>
|
||||
@@ -93,4 +71,3 @@ _(Enter route + gateway + metric)_:
|
||||
: <input type="submit" value="_(Add Route)_"><input type="button" value="_(Done)_" class="lock" onclick="done()">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ Code="e924"
|
||||
if (!isset($display['favorites'])) {
|
||||
$favorites = true;
|
||||
} else {
|
||||
$favorites = $display['favorites'] == "yes" ? true : false;
|
||||
$favorites = $display['favorites'] == "yes" ? 'true' : 'false';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
|
||||
@@ -5,9 +5,9 @@ Code="e909"
|
||||
---
|
||||
<?PHP
|
||||
if (!isset($display['favorites'])) {
|
||||
$favorites = true;
|
||||
$favorites = 'true';
|
||||
} else {
|
||||
$favorites = $display['favorites'] == "yes" ? true : false;
|
||||
$favorites = $display['favorites'] == 'yes' ? 'true' : 'false';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
Menu="NetworkSettings:1000"
|
||||
Title="_(Wireless)_ wlan0"
|
||||
Tag="fa-wifi"
|
||||
Cond="file_exists('/sys/class/net/wlan0')"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$title = _('Connect to WiFi network');
|
||||
$cfg = '/boot/config/wireless.cfg';
|
||||
if (file_exists($cfg)) $wlan0 = parse_ini_file($cfg,true)['wlan0'];
|
||||
?>
|
||||
<div class="title nocontrol shift"> </div>
|
||||
<form markdown="1" name="wifi_settings" method="POST" action="/update.php" target="progressFrame" onsubmit="enable_wifi(this.WIFI.value)">
|
||||
<input type="hidden" name="#file" value="<?=$cfg?>"/>
|
||||
<input type="hidden" name="#section" value="wlan0"/>
|
||||
<input type="hidden" name="#command" value="/webGui/scripts/wireless">
|
||||
<input type="hidden" name="#arg[1]" value=""/>
|
||||
_(Wi-Fi)_:
|
||||
: <select name="WIFI">
|
||||
<?=mk_option(_var($wlan0,'WIFI'), "no", _("Disabled"))?>
|
||||
<?=mk_option(_var($wlan0,'WIFI'), "yes", _("Enabled"))?>
|
||||
</select>
|
||||
|
||||
|
||||
: <input type="submit" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
<div id="wifi" class="hide">
|
||||
<div markdown="1" id="connected" class="shade-<?=$display['theme']?>">
|
||||
_(Connected)_:
|
||||
: <i class="fa fa-spin fa-circle-o-notch"></i>
|
||||
|
||||
</div>
|
||||
<div markdown="1" id="my_networks" class="shade-<?=$display['theme']?>">
|
||||
_(My networks)_:
|
||||
: <i class="fa fa-spin fa-circle-o-notch"></i>
|
||||
|
||||
</div>
|
||||
<div markdown="1" id="other_networks" class="shade-<?=$display['theme']?>">
|
||||
_(Other networks)_:
|
||||
: <i class="fa fa-spin fa-circle-o-notch"></i>
|
||||
|
||||
</div>
|
||||
|
||||
<div markdown="1" class="shade-<?=$display['theme']?>">
|
||||
_(Add network)_:
|
||||
: <span class="wifi"><input name="CUSTOM" type="text" class="narrow" maxlength="20" autocomplete="off" spellcheck="false" value=""></span><i class="fa fa-wifi hand grey-text" onclick="manage_wifi(encodeURIComponent($('input[name=CUSTOM]').val()),3)" title="<?=$title?>"></i>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function enable_wifi(state) {
|
||||
$('input[name="#arg[1]"]').val(state);
|
||||
}
|
||||
|
||||
function update_wifi() {
|
||||
$.post('/webGui/include/Wireless.php',{cmd:'list'},function(text) {
|
||||
if (text.length > 0) {
|
||||
var wifi = JSON.parse(text);
|
||||
$('#connected').html(wifi.active);
|
||||
$('#my_networks').html(wifi.saved);
|
||||
$('#other_networks').html(wifi.other);
|
||||
}
|
||||
});
|
||||
timers.wifi = setTimeout(update_wifi,10000);
|
||||
}
|
||||
|
||||
function manage_wifi(ssid,task) {
|
||||
if (task==2) {
|
||||
$.post('/webGui/include/Wireless.php',{cmd:'forget',ssid:ssid},function(){
|
||||
clearTimeout(timers.wifi);
|
||||
swal.close();
|
||||
setTimeout(update_wifi);
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (ssid) {
|
||||
$.post('/webGui/include/Wireless.php',{cmd:'join',ssid:ssid,task:task},function(text) {
|
||||
swal({title:decodeURIComponent(ssid),text:text,animation:'none',html:true,confirmButtonText:"_(Join this network)_",showCancelButton:true,cancelButtonText:"_(Cancel)_"},function(join){
|
||||
if (join) $('form[name=wifi]').submit();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
swal({title:"_(Missing Network Name)_",animation:'none',html:true,type:'error',confirmButtonText:"_(Ok)_"});
|
||||
}
|
||||
}
|
||||
|
||||
function showDHCP(val,v) {
|
||||
if (val=='no') {
|
||||
$('tr.static'+v).show();
|
||||
$('select[name=DNS'+v+']').val('yes');
|
||||
$('select[name=DNS'+v+'] option:eq(0)').prop('disabled',true);
|
||||
if (v=='6') $('tr.dns6').show();
|
||||
$('tr.server'+v).show();
|
||||
} else if (val=='yes') {
|
||||
$('tr.static'+v).hide();
|
||||
$('select[name=DNS'+v+']').val('no');
|
||||
$('select[name=DNS'+v+'] option:eq(0)').prop('disabled',false);
|
||||
if (v=='6') $('tr.dns6').show();
|
||||
$('tr.server'+v).hide();
|
||||
} else {
|
||||
$('tr.static'+v).hide();
|
||||
$('tr.dns'+v).hide();
|
||||
$('tr.server'+v).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function showDNS(val,v) {
|
||||
if (val=='no') $('tr.server'+v).hide();
|
||||
if (val=='yes') $('tr.server'+v).show();
|
||||
}
|
||||
|
||||
function showPassword() {
|
||||
if ($('#showPass').hasClass('checked')) {
|
||||
$('#showPass').removeClass('checked fa-eye-slash').addClass('fa-eye');
|
||||
var view = 'password';
|
||||
} else {
|
||||
$('#showPass').addClass('checked fa-eye-slash').removeClass('fa-eye');
|
||||
var view = 'text';
|
||||
}
|
||||
$('input[name="PASSWORD"]').attr('type',view);
|
||||
}
|
||||
|
||||
function showSecurity(val) {
|
||||
if (val=='none') {
|
||||
$('#username,#password').hide();
|
||||
} else if (val.slice(-1)=='e') {
|
||||
$('#username,#password').show();
|
||||
} else {
|
||||
$('#username').hide();
|
||||
$('#password').show();
|
||||
}
|
||||
}
|
||||
|
||||
<?if (_var($wlan0,'WIFI')=='yes'):?>
|
||||
$(function() {
|
||||
$('#wifi').show();
|
||||
update_wifi();
|
||||
});
|
||||
<?endif;?>
|
||||
</script>
|
||||
@@ -34,6 +34,7 @@ rtl=""
|
||||
headermetacolor=""
|
||||
headerdescription="yes"
|
||||
showBannerGradient="yes"
|
||||
favorites="yes"
|
||||
[parity]
|
||||
mode="0"
|
||||
hour="0 0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -21,10 +21,40 @@ require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
|
||||
if (isset($_POST['ntp'])) {
|
||||
if (exec("pgrep -cf /usr/sbin/ntpd")) {
|
||||
if (exec("pgrep -cf /usr/sbin/ptp4l")) {
|
||||
// ptp sync
|
||||
if (exec("pmc -ub0 'GET TIME_STATUS'|awk '$1==\"gmPresent\"{print $2;exit}'")) {
|
||||
$ptp = abs(exec("pmc -ub0 'GET CURRENT'|awk '$1==\"offsetFromMaster\"{print $2;exit}'"));
|
||||
switch (true) {
|
||||
case ($ptp == 0) : $unit = 'ns'; $ptp = '???'; break;
|
||||
case ($ptp < 1E+3): $unit = 'ns'; $ptp = round($ptp); break;
|
||||
case ($ptp < 1E+6): $unit = 'μs'; $ptp = round($ptp/1E+3); break;
|
||||
case ($ptp < 1E+9): $unit = 'ms'; $ptp = round($ptp/1E+6); break;
|
||||
default : $unit = 's' ; $ptp = round($ptp/1E+9); break;
|
||||
}
|
||||
$gm = exec("pmc -ub0 'GET CURRENT'|awk '$1==\"stepsRemoved\"{print $2;exit}'")==1 ? _('grandmaster') : _('master');
|
||||
die(sprintf(_('Clock is synchronized using %s PTP server, time offset is %s %s'),$gm,$ptp,$unit));
|
||||
} else {
|
||||
die(_('Clock is unsynchronized with no PTP servers'));
|
||||
}
|
||||
} elseif (exec("pgrep -cf /usr/sbin/ntpd")) {
|
||||
// ntp sync
|
||||
$ntp = exec("ntpq -pn|awk '$1~/^\*/{print $9;exit}'");
|
||||
die($ntp ? sprintf(_('Clock is synchronized using NTP, time offset: %s ms'),abs($ntp)) : _('Clock is unsynchronized with no NTP servers'));
|
||||
if ($ntp) {
|
||||
$ntp = abs($ntp);
|
||||
switch (true) {
|
||||
case ($ntp == 0) : $unit = 'μs'; $ntp = '< 1'; break;
|
||||
case ($ntp < 1) : $unit = 'μs'; $ntp = round($ntp*1E+3); break;
|
||||
case ($ntp < 1E+3): $unit = 'ms'; $ntp = round($ntp); break;
|
||||
default : $unit = 's' ; $ntp = round($ntp/1E+3); break;
|
||||
}
|
||||
$count = exec("ntpq -pn|grep -Pc '^[*+]'");
|
||||
die(sprintf(_('Clock is synchronized using %s NTP servers, time offset is %s %s'),$count,$ntp,$unit));
|
||||
} else {
|
||||
die(_('Clock is unsynchronized with no NTP servers'));
|
||||
}
|
||||
}
|
||||
// manual sync
|
||||
die(_('Clock is unsynchronized, free-running clock'));
|
||||
}
|
||||
|
||||
@@ -99,32 +129,32 @@ if ($_POST['vms']) {
|
||||
$arrConfig = domain_to_config($uuid);
|
||||
if ($vmrcport > 0) {
|
||||
$wsport = $lv->domain_get_ws_port($res);
|
||||
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res) ;
|
||||
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res);
|
||||
if ($vmrcprotocol == "vnc") $vmrcscale = "&resize=scale"; else $vmrcscale = "";
|
||||
$vmrcurl = autov('/plugins/dynamix.vm.manager/'.$vmrcprotocol.'.html',true).$vmrcscale.'&autoconnect=true&host=' . $_SERVER['HTTP_HOST'] ;
|
||||
if ($vmrcprotocol == "spice") $vmrcurl .= '&vmname='. urlencode($vm) . '&port=/wsproxy/'.$vmrcport.'/' ; else $vmrcurl .= '&port=&path=/wsproxy/' . $wsport . '/';
|
||||
$vmrcurl = autov('/plugins/dynamix.vm.manager/'.$vmrcprotocol.'.html',true).$vmrcscale.'&autoconnect=true&host=' . $_SERVER['HTTP_HOST'];
|
||||
if ($vmrcprotocol == "spice") $vmrcurl .= '&vmname='. urlencode($vm) . '&port=/wsproxy/'.$vmrcport.'/'; else $vmrcurl .= '&port=&path=/wsproxy/' . $wsport . '/';
|
||||
} elseif ($vmrcport == -1 || $autoport) {
|
||||
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res) ;
|
||||
if ($autoport == "yes") $auto = "auto" ; else $auto="manual" ;
|
||||
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res);
|
||||
$auto = ($autoport == "yes") ? "auto" : "manual";
|
||||
} elseif (!empty($arrConfig['gpu'])) {
|
||||
$arrValidGPUDevices = getValidGPUDevices();
|
||||
foreach ($arrConfig['gpu'] as $arrGPU) {
|
||||
foreach ($arrValidGPUDevices as $arrDev) {
|
||||
if ($arrGPU['id'] == $arrDev['id']) {
|
||||
if (count(array_filter($arrValidGPUDevices, function($v) use ($arrDev) { return $v['name'] == $arrDev['name']; })) > 1) {
|
||||
$vmrcprotocol = "VGA" ;
|
||||
$vmrcprotocol = "VGA";
|
||||
} else {
|
||||
$vmrcprotocol = "VGA" ;
|
||||
$vmrcprotocol = "VGA";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$template = $lv->_get_single_xpath_result($res, '//domain/metadata/*[local-name()=\'vmtemplate\']/@name');
|
||||
if (empty($template)) $template = 'Custom';
|
||||
$log = (is_file("/var/log/libvirt/qemu/$vm.log") ? "libvirt/qemu/$vm.log" : '');
|
||||
if (!isset($domain_cfg["CONSOLE"])) $vmrcconsole = "web" ; else $vmrcconsole = $domain_cfg["CONSOLE"] ;
|
||||
if (!isset($domain_cfg["RDPOPT"])) $vmrcconsole .= ";no" ; else $vmrcconsole .= ";".$domain_cfg["RDPOPT"] ;
|
||||
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')\"", addslashes($vm), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), addslashes($log),addslashes($fstype), $vmrcconsole,false,addslashes(str_replace('"',"'",$WebUI)));
|
||||
$icon = $lv->domain_get_icon_url($res);
|
||||
@@ -153,7 +183,7 @@ if ($_POST['vms']) {
|
||||
#Build VM Usage array.
|
||||
$menuusage = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), addslashes($log),addslashes($fstype), $vmrcconsole,true,addslashes(str_replace('"',"'",$WebUI)));
|
||||
$vmusagehtml[] = "<span class='outer solid vmsuse $status'><span id='vmusage-$uuid' $menuusage class='hand'>$image</span><span class='inner'>$vm<br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span>";
|
||||
$vmusagehtml[] = "<br><br><span id='vmmetrics-gcpu-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><br><span id='vmmetrics-gcpu-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-hcpu-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-mem-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-disk-".$uuid."'>"._("Loading")."....</span>";
|
||||
|
||||
@@ -20,6 +20,7 @@ $themes2 = in_array($theme,['gray','azure']);
|
||||
$config = "/boot/config";
|
||||
$entity = $notify['entity'] & 1 == 1;
|
||||
$alerts = '/tmp/plugins/my_alerts.txt';
|
||||
$wlan0 = file_exists('/sys/class/net/wlan0');
|
||||
|
||||
// adjust the text color in docker log window
|
||||
$fgcolor = in_array($theme,['white','azure']) ? '#1c1c1c' : '#f2f2f2';
|
||||
@@ -77,6 +78,7 @@ html{font-size:<?=$display['font']?>%}
|
||||
<?endif;?>
|
||||
<?
|
||||
$nchan = ['webGui/nchan/notify_poller','webGui/nchan/session_check'];
|
||||
if ($wlan0) $nchan[] = 'webGui/nchan/wlan0';
|
||||
$safemode = _var($var,'safeMode')=='yes';
|
||||
$tasks = find_pages('Tasks');
|
||||
$buttons = find_pages('Buttons');
|
||||
@@ -252,7 +254,7 @@ function openWindow(cmd,title,height,width) {
|
||||
}
|
||||
function openTerminal(tag,name,more) {
|
||||
if (/MSIE|Edge/.test(navigator.userAgent)) {
|
||||
swal({title:"_(Unsupported Feature)_",text:"_(Sorry, this feature is not supported by MSIE/Edge)_.<br>_(Please try a different browser)_",type:'error',html:true,confirmButtonText:"_(Ok)_"});
|
||||
swal({title:"_(Unsupported Feature)_",text:"_(Sorry, this feature is not supported by MSIE/Edge)_.<br>_(Please try a different browser)_",type:'error',html:true,animation:'none',confirmButtonText:"_(Ok)_"});
|
||||
return;
|
||||
}
|
||||
// open terminal window (run in background)
|
||||
@@ -409,7 +411,7 @@ function openDone(data) {
|
||||
if (data == '_DONE_') {
|
||||
$('div.spinner.fixed').hide();
|
||||
$('button.confirm').text("<?=_('Done')?>").prop('disabled',false).show();
|
||||
if ( typeof ca_done_override !== 'undefined' ) {
|
||||
if (typeof ca_done_override !== 'undefined') {
|
||||
if (ca_done_override == true) {
|
||||
$("button.confirm").trigger("click");
|
||||
ca_done_override = false;
|
||||
@@ -529,7 +531,7 @@ function hideUpgrade(set) { /** @note can likely be removed, not used in webgui
|
||||
}
|
||||
function confirmUpgrade(confirm) {
|
||||
if (confirm) {
|
||||
swal({title:"<?=_('Update')?> Unraid OS",text:"<?=_('Do you want to update to the new version')?>?",type:'warning',html:true,showCancelButton:true,closeOnConfirm:false,confirmButtonText:"<?=_('Proceed')?>",cancelButtonText:"<?=_('Cancel')?>"},function(){
|
||||
swal({title:"<?=_('Update')?> Unraid OS",text:"<?=_('Do you want to update to the new version')?>?",type:'warning',html:true,animation:'none',showCancelButton:true,closeOnConfirm:false,confirmButtonText:"<?=_('Proceed')?>",cancelButtonText:"<?=_('Cancel')?>"},function(){
|
||||
openPlugin("plugin update unRAIDServer.plg","<?=_('Update')?> Unraid OS");
|
||||
});
|
||||
} else {
|
||||
@@ -654,6 +656,7 @@ $.ajaxPrefilter(function(s, orig, xhr){
|
||||
</div>
|
||||
<?include "$docroot/plugins/dynamix.my.servers/include/myservers2.php"?>
|
||||
</div>
|
||||
<a href="#" class="move_to_end" title="<?=_('Move To End')?>"><i class="fa fa-arrow-circle-down"></i></a>
|
||||
<a href="#" class="back_to_top" title="<?=_('Back To Top')?>"><i class="fa fa-arrow-circle-up"></i></a>
|
||||
<?
|
||||
// Build page menus
|
||||
@@ -720,7 +723,7 @@ if (isset($myPage['Load']) && $myPage['Load']>0) echo "\n<script>timers.reload =
|
||||
echo "<div class='tabs'>";
|
||||
$tab = 1;
|
||||
$pages = [];
|
||||
if (!empty($myPage['text']) && page_enabled($myPage)) $pages[$myPage['name']] = $myPage;
|
||||
if (!empty($myPage['text'])) $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 +731,7 @@ $tabbed = $display['tabs']==0 && count($pages)>1;
|
||||
foreach ($pages as $page) {
|
||||
$close = false;
|
||||
if (isset($page['Title'])) {
|
||||
eval("\$title=\"{$page['Title']}\";");
|
||||
eval("\$title=\"".htmlspecialchars($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 +748,7 @@ foreach ($pages as $page) {
|
||||
if (isset($page['Type']) && $page['Type']=='menu') {
|
||||
$pgs = find_pages($page['name']);
|
||||
foreach ($pgs as $pg) {
|
||||
@eval("\$title=\"{$pg['Title']}\";");
|
||||
@eval("\$title=\"".htmlspecialchars($pg['Title'])."\";");
|
||||
$icon = _var($pg,'Icon',"<i class='icon-app PanelIcon'></i>");
|
||||
if (substr($icon,-4)=='.png') {
|
||||
$root = $pg['root'];
|
||||
@@ -820,6 +823,7 @@ default:
|
||||
echo "<span class='green strong'><i class='fa fa-play-circle'></i> ",_('Array Started'),"</span>$progress"; break;
|
||||
}
|
||||
echo "</span></span><span id='countdown'></span><span id='user-notice' class='red-text'></span>";
|
||||
if ($wlan0) echo "<span id='wlan0' class='grey-text' onclick='wlanSettings()'><i class='fa fa-wifi fa-fw'></i></span>";
|
||||
echo "<span id='copyright'>Unraid® webGui ©2024, Lime Technology, Inc.";
|
||||
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>";
|
||||
@@ -923,6 +927,20 @@ defaultPage.on('message', function(msg,meta) {
|
||||
}
|
||||
});
|
||||
|
||||
<?if ($wlan0):?>
|
||||
function wlanSettings() {
|
||||
$.cookie('one','tab<?=count(glob("$docroot/webGui/Eth*.page"))?>');
|
||||
window.location = '/Settings/NetworkSettings';
|
||||
}
|
||||
|
||||
var nchan_wlan0 = new NchanSubscriber('/sub/wlan0',{subscriber:'websocket'});
|
||||
nchan_wlan0.on('message', function(msg) {
|
||||
var wlan = JSON.parse(msg);
|
||||
$('#wlan0').removeClass().addClass(wlan.color).attr('title',wlan.title);
|
||||
});
|
||||
nchan_wlan0.start();
|
||||
<?endif;?>
|
||||
|
||||
var nchan_plugins = new NchanSubscriber('/sub/plugins',{subscriber:'websocket'});
|
||||
nchan_plugins.on('message', function(data) {
|
||||
if (!data || openDone(data)) return;
|
||||
@@ -1034,13 +1052,12 @@ nchan_vmaction.on('message', function(data) {
|
||||
box.scrollTop(box[0].scrollHeight);
|
||||
});
|
||||
|
||||
var backtotopoffset = 250;
|
||||
var backtotopduration = 500;
|
||||
const scrollDuration = 500;
|
||||
$(window).scroll(function() {
|
||||
if ($(this).scrollTop() > backtotopoffset) {
|
||||
$('.back_to_top').fadeIn(backtotopduration);
|
||||
if ($(this).scrollTop() > 0) {
|
||||
$('.back_to_top').fadeIn(scrollDuration);
|
||||
} else {
|
||||
$('.back_to_top').fadeOut(backtotopduration);
|
||||
$('.back_to_top').fadeOut(scrollDuration);
|
||||
}
|
||||
<?if ($themes1):?>
|
||||
var top = $('div#header').height()-1; // header height has 1 extra pixel to cover overlap
|
||||
@@ -1049,9 +1066,16 @@ $(window).scroll(function() {
|
||||
$('div.upgrade_notice').css($(this).scrollTop() > 24 ? {position:'fixed',top:'0'} : {position:'absolute',top:'24px'});
|
||||
<?endif;?>
|
||||
});
|
||||
|
||||
$('.move_to_end').click(function(event) {
|
||||
event.preventDefault();
|
||||
$('html,body').animate({scrollTop:$(document).height()},scrollDuration);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.back_to_top').click(function(event) {
|
||||
event.preventDefault();
|
||||
$('html,body').animate({scrollTop:0},backtotopduration);
|
||||
$('html,body').animate({scrollTop:0},scrollDuration);
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -1128,6 +1152,7 @@ $(function() {
|
||||
});
|
||||
}
|
||||
$('form').append($('<input>').attr({type:'hidden', name:'csrf_token', value:csrf_token}));
|
||||
setInterval(function(){if ($(document).height() > $(window).height()) $('.move_to_end').fadeIn(scrollDuration); else $('.move_to_end').fadeOut(scrollDuration);},250);
|
||||
});
|
||||
|
||||
var gui_pages_available = [];
|
||||
@@ -1147,56 +1172,45 @@ function isValidURL(url) {
|
||||
}
|
||||
}
|
||||
|
||||
$('body').on("click","a,.ca_href", function(e) {
|
||||
if ($(this).hasClass("ca_href") ) {
|
||||
$('body').on('click','a,.ca_href', function(e) {
|
||||
if ($(this).hasClass('ca_href')) {
|
||||
var ca_href = true;
|
||||
var href=$(this).attr("data-href");
|
||||
var target=$(this).attr("data-target");
|
||||
var href=$(this).attr('data-href');
|
||||
var target=$(this).attr('data-target');
|
||||
} else {
|
||||
var ca_href = false;
|
||||
var href = $(this).attr("href");
|
||||
var target = $(this).attr("target");
|
||||
var href = $(this).attr('href');
|
||||
var target = $(this).attr('target');
|
||||
}
|
||||
if ( href ) {
|
||||
if (href) {
|
||||
href = href.trim();
|
||||
if ( href.match('https?://[^\.]*.(my)?unraid.net/') || href.indexOf("https://unraid.net/") == 0 || href == "https://unraid.net" || href.indexOf("http://lime-technology.com") == 0) {
|
||||
if ( ca_href ) {
|
||||
window.open(href,target);
|
||||
}
|
||||
// Sanitize href to prevent XSS
|
||||
href = href.replace(/[<>"]/g, '');
|
||||
if (href.match('https?://[^\.]*.(my)?unraid.net/') || href.indexOf('https://unraid.net/') == 0 || href == 'https://unraid.net' || href.indexOf('http://lime-technology.com') == 0) {
|
||||
if (ca_href) window.open(href,target);
|
||||
return;
|
||||
}
|
||||
|
||||
if (href !== "#" && href.indexOf("javascript") !== 0) {
|
||||
}
|
||||
if (href !== '#' && href.indexOf('javascript') !== 0) {
|
||||
var dom = isValidURL(href);
|
||||
if ( dom == false ) {
|
||||
if ( href.indexOf("/") == 0 ) { // all internal links start with "/"
|
||||
return;
|
||||
if (dom == false) {
|
||||
if (href.indexOf('/') == 0) return; // all internal links start with "/"
|
||||
var baseURLpage = href.split('/');
|
||||
if (gui_pages_available.includes(baseURLpage[0])) return;
|
||||
}
|
||||
var baseURLpage = href.split("/");
|
||||
if ( gui_pages_available.includes(baseURLpage[0]) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ( $(this).hasClass("localURL") ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($(this).hasClass('localURL')) return;
|
||||
try {
|
||||
var domainsAllowed = JSON.parse($.cookie("allowedDomains"));
|
||||
var domainsAllowed = JSON.parse($.cookie('allowedDomains'));
|
||||
} catch(e) {
|
||||
var domainsAllowed = new Object();
|
||||
}
|
||||
$.cookie("allowedDomains",JSON.stringify(domainsAllowed),{expires:3650}); // rewrite cookie to further extend expiration by 400 days
|
||||
|
||||
if ( domainsAllowed[dom.hostname] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.cookie('allowedDomains',JSON.stringify(domainsAllowed),{expires:3650}); // rewrite cookie to further extend expiration by 400 days
|
||||
if (domainsAllowed[dom.hostname]) return;
|
||||
e.preventDefault();
|
||||
swal({
|
||||
title: "<?=_('External Link')?>",
|
||||
text: "<span title='"+href+"'><?=_('Clicking OK will take you to a 3rd party website not associated with Lime Technology')?><br><br><b>"+href+"<br><br><input id='Link_Always_Allow' type='checkbox'></input><?=_('Always Allow')?> "+dom.hostname+"</span>",
|
||||
html: true,
|
||||
animation: 'none',
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
showConfirmButton: true,
|
||||
@@ -1204,16 +1218,14 @@ $('body').on("click","a,.ca_href", function(e) {
|
||||
confirmButtonText: "<?=_('OK')?>"
|
||||
},function(isConfirm) {
|
||||
if (isConfirm) {
|
||||
if ( $("#Link_Always_Allow").is(":checked") ) {
|
||||
if ($('#Link_Always_Allow').is(':checked')) {
|
||||
domainsAllowed[dom.hostname] = true;
|
||||
$.cookie("allowedDomains",JSON.stringify(domainsAllowed),{expires:3650});
|
||||
$.cookie('allowedDomains',JSON.stringify(domainsAllowed),{expires:3650});
|
||||
}
|
||||
var popupOpen = window.open(href,target);
|
||||
if ( !popupOpen || popupOpen.closed || typeof popupOpen == "undefined" ) {
|
||||
var popupWarning = addBannerWarning("<?=_('Popup Blocked.');?>");
|
||||
setTimeout(function() {
|
||||
removeBannerWarning(popupWarning);}
|
||||
,10000);
|
||||
if (!popupOpen || popupOpen.closed || typeof popupOpen == 'undefined') {
|
||||
var popupWarning = addBannerWarning("<?=_('Popup Blocked');?>");
|
||||
setTimeout(function(){removeBannerWarning(popupWarning);},10000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -14,6 +14,7 @@
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
|
||||
$charts = '/var/tmp/charts_data.tmp';
|
||||
$cookie = '/boot/config/dashboard_settings.json';
|
||||
|
||||
switch ($_POST['cmd']) {
|
||||
case 'get':
|
||||
@@ -22,5 +23,8 @@ case 'get':
|
||||
case 'set':
|
||||
file_put_contents($charts,$_POST['data']);
|
||||
break;
|
||||
case 'cookie':
|
||||
file_put_contents($cookie,$_POST['data']);
|
||||
break;
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'settings';
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
if (isset($_POST['listen'])) {
|
||||
die(exec("$docroot/webGui/scripts/show_interfaces")?:_('Any'));
|
||||
}
|
||||
|
||||
function port($eth) {
|
||||
$sys = "/sys/class/net";
|
||||
if (substr($eth,0,4)=='wlan') return $eth;
|
||||
$x = preg_replace('/[^0-9]/','',$eth);
|
||||
return file_exists("$sys/br{$x}") ? "br${x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
|
||||
}
|
||||
|
||||
exec("grep -Po 'nameserver \K\S+' /etc/resolv.conf 2>/dev/null",$ns);
|
||||
$eth = $_POST['port'];
|
||||
$vlan = $_POST['vlan'];
|
||||
$port = port($eth).($vlan ? ".$vlan" : "");
|
||||
$v6on = trim(file_get_contents("/proc/sys/net/ipv6/conf/$port/disable_ipv6"))==='0';
|
||||
$none = _('None');
|
||||
$error = "<span class='red-text'>"._('Missing')."</span>";
|
||||
$note = in_array($eth,['eth0','wlan0']) && !$vlan ? $error : $none;
|
||||
$link = _(ucfirst(exec("ethtool $eth 2>/dev/null | awk '$1==\"Link\" {print $3;exit}'")) ?: 'Unknown')." ("._(exec("ethtool $eth 2>/dev/null | grep -Pom1 '^\s+Port: \K.*'") ?: ($eth=='wlan0' ? 'wifi' :'not present')).")";
|
||||
$speed = _(preg_replace(['/^(\d+)/','/!/'],['$1 ',''],exec("ethtool $eth 2>/dev/null | awk '$1==\"Speed:\" {print $2;exit}'")) ?: 'Unknown');
|
||||
$ipv4 = array_filter(explode(' ',exec("ip -4 -br addr show $port scope global 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
|
||||
$gw4 = exec("ip -4 route show default dev $port 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
|
||||
$dns4 = array_filter($ns,function($ns){return strpos($ns,':')===false;});
|
||||
$domain = exec("grep -Pom1 'domain \K.*' /etc/resolv.conf 2>/dev/null") ?: '---';
|
||||
|
||||
if ($v6on) {
|
||||
$ipv6 = array_filter(explode(' ',exec("ip -6 -br addr show $port scope global -temporary 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
|
||||
$gw6 = exec("ip -6 route show default dev $port 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
|
||||
$dns6 = array_filter($ns,function($ns){return strpos($ns,':')!==false;});
|
||||
}
|
||||
|
||||
echo "<table style='text-align:left;font-size:1.2rem'>";
|
||||
echo "<tr><td> </td><td> </td></tr>";
|
||||
echo "<tr><td>"._('Interface link').":</td><td>$link</td></tr>";
|
||||
echo "<tr><td>"._('Interface speed').":</td><td>$speed</td></tr>";
|
||||
if ($eth=='wlan0') {
|
||||
$ini = '/boot/config/wireless-networks.cfg';
|
||||
$wifi = (array)@parse_ini_file($ini,true);
|
||||
$att1 = $att2 = $att3 = '';
|
||||
foreach ($wifi as $network => $option) {
|
||||
if (isset($option['GROUP']) && $option['GROUP']=='active') {
|
||||
$att1 = $network;
|
||||
$att2 = $option['ATTR2'];
|
||||
$att3 = $option['ATTR3'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($att1) echo "<tr><td>"._('Network').":</td><td>$att1</td></tr>";
|
||||
if ($att2) echo "<tr><td>"._('Health').":</td><td>$att2</td></tr>";
|
||||
if ($att3) echo "<tr><td>"._('Security').":</td><td>$att3</td></tr>";
|
||||
}
|
||||
if (count($ipv4)) foreach ($ipv4 as $ip) {
|
||||
echo "<tr><td>"._('IPv4 address').":</td><td>$ip</td></tr>";
|
||||
} else {
|
||||
echo "<tr><td>"._('IPv4 address').":</td><td>$note</td></tr>";
|
||||
}
|
||||
echo "<tr><td>"._('IPv4 default gateway').":</td><td>$gw4</td></tr>";
|
||||
if (count($dns4)) foreach ($dns4 as $dns) {
|
||||
echo "<tr><td>"._('IPv4 DNS server').":</td><td>$dns</td></tr>";
|
||||
} else {
|
||||
echo "<tr><td>"._('IPv4 DNS server').":</td><td>$error</td></tr>";
|
||||
}
|
||||
if ($v6on) {
|
||||
if (count($ipv6)) foreach ($ipv6 as $ip) {
|
||||
echo "<tr><td>"._('IPv6 address').":</td><td>$ip</td></tr>";
|
||||
} else {
|
||||
echo "<tr><td>"._('IPv6 address').":</td><td>$note</td></tr>";
|
||||
}
|
||||
echo "<tr><td>"._('IPv6 default gateway').":</td><td>$gw6</td></tr>";
|
||||
if (count($dns6)) foreach ($dns6 as $dns) {
|
||||
echo "<tr><td>"._('IPv6 DNS server').":</td><td>$dns</td></tr>";
|
||||
} else {
|
||||
echo "<tr><td>"._('IPv6 DNS server').":</td><td>$error</td></tr>";
|
||||
}
|
||||
}
|
||||
echo "<tr><td>"._('Domain name').":</td><td>$domain</td></tr>";
|
||||
echo "</table>";
|
||||
?>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -26,8 +26,8 @@ case 'Add Route':
|
||||
if ($gateway && $route) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$gateway}_{$route}_{$metric}_add"));
|
||||
break;
|
||||
default:
|
||||
exec("ip -4 route show table all|grep -Pv '^(127\\.0\\.0\\.0)|table local'",$ipv4);
|
||||
exec("ip -6 route show table all|grep -Pv '^([am:]|(f[ef][0-9][0-9])::)|expires|table local'",$ipv6);
|
||||
exec("ip -4 route show table all|grep -Pv '^(127\\.0\\.0\\.0)|table local|unreachable'",$ipv4);
|
||||
exec("ip -6 route show table all|grep -Pv '^([am:]|(f[ef][0-9][0-9])::)|expires|table local|unreachable'",$ipv6);
|
||||
foreach ($ipv4 as $info) {
|
||||
$cell = explode(' ',$info);
|
||||
$route = $cell[0];
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?PHP
|
||||
// start/stop service
|
||||
exec("/etc/rc.d/rc.ptpd ".escapeshellarg($_POST['cmd']));
|
||||
?>
|
||||
@@ -0,0 +1,218 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
|
||||
$var = '/var/local/emhttp/var.ini';
|
||||
$cfg = '/boot/config/wireless.cfg';
|
||||
$ssl = '/etc/rc.d/rc.ssl.input';
|
||||
$tmp = '/var/tmp/attr';
|
||||
$wifi = is_readable($cfg) ? (array)parse_ini_file($cfg,true) : [];
|
||||
$attr = is_readable($tmp) ? (array)parse_ini_file($tmp,true) : [];
|
||||
$md5 = md5(json_encode($attr),true);
|
||||
$cmd = $_POST['cmd'];
|
||||
$masks = [
|
||||
'255.0.0.0' => '8', '255.255.0.0' => '16', '255.255.128.0' => '17', '255.255.192.0' => '18',
|
||||
'255.255.224.0' => '19', '255.255.240.0' => '20', '255.255.248.0' => '21', '255.255.252.0' => '22',
|
||||
'255.255.254.0' => '23', '255.255.255.0' => '24', '255.255.255.128' => '25', '255.255.255.192' => '26',
|
||||
'255.255.255.224' => '27', '255.255.255.240' => '28', '255.255.255.248' => '29', '255.255.255.252' => '30'
|
||||
];
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'settings';
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
|
||||
function scanWifi($port) {
|
||||
$wlan = [];
|
||||
exec("iw ".escapeshellarg($port)." scan | grep -P '^BSS|signal:|SSID:|Authentication suites:'",$scan);
|
||||
$n = -1;
|
||||
for ($i=0; $i<count($scan); $i++) {
|
||||
if (substr($scan[$i],0,3)=='BSS') {
|
||||
$wlan[++$n]['bss'] = substr($scan[$i],4,17);
|
||||
} elseif (strpos($scan[$i],'signal:')!==false) {
|
||||
$wlan[$n]['signal'] = trim(explode(': ',$scan[$i])[1]);
|
||||
} elseif (strpos($scan[$i],'SSID:')!==false) {
|
||||
$wlan[$n]['ssid'] = trim(explode(': ',$scan[$i])[1]);
|
||||
} elseif (strpos($scan[$i],'Authentication suites:')!==false) {
|
||||
$wlan[$n]['security'] = trim(explode(': ',$scan[$i])[1]);
|
||||
}
|
||||
}
|
||||
return array_values(array_intersect_key($wlan,array_unique(array_column($wlan,'ssid'))));
|
||||
}
|
||||
|
||||
function saveWifi() {
|
||||
global $cfg, $wifi;
|
||||
$text = [];
|
||||
foreach ($wifi as $network => $block) {
|
||||
$text[] = "[$network]";
|
||||
foreach ($block as $key => $value) $text[] = "$key=\"$value\"";
|
||||
}
|
||||
file_put_contents_atomic($cfg,implode("\n",$text)."\n");
|
||||
}
|
||||
|
||||
function saveAttr() {
|
||||
global $tmp, $attr, $md5;
|
||||
$text = [];
|
||||
if (md5(json_encode($attr),true) === $md5) return;
|
||||
foreach ($attr as $network => $block) {
|
||||
$text[] = "[$network]";
|
||||
foreach ($block as $key => $value) $text[] = "$key=\"$value\"";
|
||||
}
|
||||
file_put_contents_atomic($tmp,implode("\n",$text)."\n");
|
||||
}
|
||||
|
||||
switch ($cmd) {
|
||||
case 'list':
|
||||
$title = _('Connect to WiFi network');
|
||||
$port = array_key_first($wifi);
|
||||
$carrier = "/sys/class/net/$port/carrier";
|
||||
$wlan = scanWifi($port);
|
||||
$echo = [];
|
||||
$index = 0;
|
||||
if (count(array_column($wlan,'ssid'))) {
|
||||
$up = file_exists($carrier) && file_get_contents($carrier)==1;
|
||||
$alive = $up ? exec("iw ".escapeshellarg($port)." link 2>/dev/null | grep -Pom1 'SSID: \K.+'") : '';
|
||||
$state = $up ? _('Connected') : _('Disconnected');
|
||||
$color = $up ? 'blue' : 'red';
|
||||
|
||||
foreach (array_column($wlan,'ssid') as $network) {
|
||||
$attr[$network]['ATTR1'] = $wlan[$index]['bss'];
|
||||
$attr[$network]['ATTR2'] = $wlan[$index]['signal'];
|
||||
$attr[$network]['ATTR3'] = $wlan[$index]['security'];
|
||||
$index++;
|
||||
if (isset($wifi[$network]['GROUP'])) {
|
||||
if ($network == $alive || $wifi[$network]['GROUP'] == 'active') {
|
||||
$echo['active'][] = "<dl><dt>$state:</dt>";
|
||||
$echo['active'][] = "<dd><span class=\"wifi\">$network</span><i class=\"fa fa-fw fa-wifi hand $color-text\" onclick=\"manage_wifi(encodeURIComponent('$network'),1)\" title=\"$title\"></i><input type=\"button\" class=\"form\" value=\""._('Info')."\" onclick=\"networkInfo('$port')\"></dd>";
|
||||
} else {
|
||||
$echo['saved'][] = empty($echo['saved']) ? "<dl><dt>"._('My networks').":</dt>" : "<dt> </dt>";
|
||||
$echo['saved'][] = "<dd><span class=\"wifi\">$network</span><i class=\"fa fa-wifi hand blue-text\" onclick=\"manage_wifi(encodeURIComponent('$network'),1)\" title=\"$title\"></i></dd>";
|
||||
}
|
||||
} else {
|
||||
$echo['other'][] = empty($echo['other']) ? "<dl><dt>"._('Other networks').":</dt>" : "<dt> </dt>";
|
||||
$echo['other'][] = "<dd><span class=\"wifi\">$network</span><i class=\"fa fa-wifi hand grey-text\" onclick=\"manage_wifi(encodeURIComponent('$network'),0)\" title=\"$title\"></i></dd>";
|
||||
}
|
||||
}
|
||||
if (empty($echo['active'])) $echo['active'][] = "<dl><dt>"._('Connected').":</dt><dd>"._('None')."</dd>";
|
||||
if (empty($echo['saved'])) $echo['saved'][] = "<dl><dt>"._('My networks').":</dt><dd>"._('None')."</dd>";
|
||||
if (empty($echo['other'])) $echo['other'][] = "<dl><dt>"._('Other networks').":</dt><dd>"._('None')."</dd>";
|
||||
$echo['active'] = implode($echo['active']);
|
||||
$echo['saved'] = implode($echo['saved']);
|
||||
$echo['other'] = implode($echo['other']);
|
||||
saveAttr();
|
||||
}
|
||||
echo json_encode($echo);
|
||||
break;
|
||||
case 'join':
|
||||
if (is_readable($ssl)) extract(parse_ini_file($ssl));
|
||||
$token = parse_ini_file($var)['csrf_token'];
|
||||
$ssid = rawurldecode($_POST['ssid']);
|
||||
$drop = $_POST['task']==1;
|
||||
$manual = $_POST['task']==3;
|
||||
$user = _var($wifi[$ssid],'USERNAME') && isset($cipher,$key,$iv) ? openssl_decrypt($wifi[$ssid]['USERNAME'],$cipher,$key,0,$iv) : _var($wifi[$ssid],'USERNAME');
|
||||
$passwd = _var($wifi[$ssid],'PASSWORD') && isset($cipher,$key,$iv) ? openssl_decrypt($wifi[$ssid]['PASSWORD'],$cipher,$key,0,$iv) : _var($wifi[$ssid],'PASSWORD');
|
||||
$join = _var($wifi[$ssid],'AUTOJOIN','no');
|
||||
$dhcp4 = _var($wifi[$ssid],'DHCP4','yes');
|
||||
$dns4 = _var($wifi[$ssid],'DNS4','no');
|
||||
$ip4 = _var($wifi[$ssid],'IP4');
|
||||
$mask4 = _var($wifi[$ssid],'MASK4','255.255.255.0');
|
||||
$gw4 = _var($wifi[$ssid],'GATEWAY4');
|
||||
$server4 = _var($wifi[$ssid],'SERVER4');
|
||||
$dhcp6 = _var($wifi[$ssid],'DHCP6');
|
||||
$dns6 = _var($wifi[$ssid],'DNS6','no');
|
||||
$ip6 = _var($wifi[$ssid],'IP6');
|
||||
$mask6 = _var($wifi[$ssid],'MASK6','64');
|
||||
$gwv6 = _var($wifi[$ssid],'GATEWAY6');
|
||||
$server6 = _var($wifi[$ssid],'SERVER6');
|
||||
$safe = _var($wifi[$ssid],'SECURITY');
|
||||
$attr1 = $attr[$ssid]['ATTR1'];
|
||||
$attr2 = $attr[$ssid]['ATTR2'];
|
||||
$attr3 = $attr[$ssid]['ATTR3'];
|
||||
$ieee1 = strpos($attr3,'IEEE')!==false;
|
||||
$ieee2 = strpos($safe,'IEEE')!==false;
|
||||
$hide0 = ($manual || !$ieee2) && !$ieee1 ? 'hide' : '';
|
||||
$hide1 = $safe=='OPEN' || !$attr3 ? 'hide' : '';
|
||||
$hide2 = $dhcp4=='no' ? '': 'hide';
|
||||
$hide3 = $dns4=='no' ? 'hide' : '';
|
||||
$hide4 = $dhcp6=='no' ? '' : 'hide';
|
||||
$hide5 = $dhcp6=='' ? 'hide' : '';
|
||||
$hide6 = $dns6=='no' ? 'hide' : '';
|
||||
echo "<form name=\"wifi\" method=\"POST\" action=\"/update.php\" target=\"progressFrame\">";
|
||||
echo "<input type=\"hidden\" name=\"#file\" value=\"$cfg\">";
|
||||
echo "<input type=\"hidden\" name=\"#include\" value=\"/webGui/include/update.wireless.php\">";
|
||||
echo "<input type=\"hidden\" name=\"#command\" value=\"/webGui/scripts/wireless\">";
|
||||
echo "<input type=\"hidden\" name=\"#section\" value=\"$ssid\">";
|
||||
echo "<input type=\"hidden\" name=\"ATTR1\" value=\"$attr1\">";
|
||||
echo "<input type=\"hidden\" name=\"ATTR2\" value=\"$attr2\">";
|
||||
echo "<input type=\"hidden\" name=\"ATTR3\" value=\"$attr3\">";
|
||||
echo "<input type=\"hidden\" name=\"csrf_token\" value=\"$token\">";
|
||||
echo "<table class=\"swal\">";
|
||||
echo "<tr><td colspan=\"2\"> </td></tr>";
|
||||
if ($drop && isset($wifi[$ssid])) {
|
||||
echo "<tr><td colspan=\"2\"><center><input type=\"button\" class=\"form\" value=\""._('Forget this network')."\" onclick=\"manage_wifi(encodeURIComponent('$ssid'),2)\"></center></td></tr>";
|
||||
echo "<tr><td colspan=\"2\"> </td></tr>";
|
||||
}
|
||||
if ($manual || $safe) {
|
||||
echo "<tr><td>"._('Security')."</td><td><select name=\"SECURITY\" onclick=\"showSecurity(this.value)\">";
|
||||
echo mk_option($safe, 'OPEN', _('None'));
|
||||
echo mk_option($safe, 'WEP', _('WEP (deprecated)'));
|
||||
echo mk_option($safe, 'PSK', _('WPA2'));
|
||||
echo mk_option($safe, 'PSK SAE', _('WPA2/WPA3'));
|
||||
echo mk_option($safe, 'SAE', _('WPA3'));
|
||||
echo mk_option($safe, 'IEEE 802.1X', _('WPA2 Enterprise'));
|
||||
echo mk_option($safe, 'IEEE 802.1X IEEE 802.1X/SHA-256', _('WPA2/WPA3 Enterprise'));
|
||||
echo mk_option($safe, 'IEEE 802.1X/SHA-256', _('WPA3 Enterprise'));
|
||||
echo "</select></td></tr>";
|
||||
}
|
||||
if ($ieee1 || $manual || $safe) echo "<tr id=\"username\" class=\"$hide0\"><td>"._('Username').":</td><td><input type=\"text\" name=\"USERNAME\" class=\"narrow\" autocomplete=\"off\" spellcheck=\"false\" value=\"$user\"></td></tr>";
|
||||
if ($attr3 || $manual || $safe) echo "<tr id=\"password\" class=\"$hide1\"><td>"._('Password').":</td><td><input type=\"password\" name=\"PASSWORD\" class=\"narrow\" autocomplete=\"off\" spellcheck=\"false\" value=\"$passwd\"><i id=\"showPass\" class=\"fa fa-eye\" onclick=\"showPassword()\"></i></td></tr>";
|
||||
echo "<tr><td colspan=\"2\"> </td></tr>";
|
||||
echo "<tr><td>"._('IPv4 address assignment').":</td><td><select name=\"DHCP4\" onclick=\"showDHCP(this.value,4)\">";
|
||||
echo mk_option($dhcp4, 'yes', _('Automatic'));
|
||||
echo mk_option($dhcp4, 'no', _('Static'));
|
||||
echo "</select></td></tr>";
|
||||
echo "<tr class=\"static4 $hide2\"><td>"._('IPv4 address').":</td><td><input type=\"text\" name=\"IP4\" class=\"narrow\" maxlength=\"15\" autocomplete=\"off\" spellcheck=\"false\" value=\"$ip4\">/<select name=\"MASK4\" class=\"slim\">";
|
||||
foreach ($masks as $mask => $prefix) echo mk_option($mask4, $mask, $prefix);
|
||||
echo "</select></td></tr>";
|
||||
echo "<tr class=\"static4 $hide2\"><td>"._('IPv4 default gateway').":</td><td><input type=\"text\" name=\"GATEWAY4\" class=\"narrow\" maxlength=\"15\" autocomplete=\"off\" spellcheck=\"false\" value=\"$gw4\"></td></tr>";
|
||||
echo "<tr class=\"dns4\"><td>"._('IPv4 DNS assignment').":</td><td><select name=\"DNS4\" onclick=\"showDNS(this.value,4)\">";
|
||||
echo mk_option($dns4, "no", _("Automatic"));
|
||||
echo mk_option($dns4, "yes", _("Static"));
|
||||
echo "</select></td></tr>";
|
||||
echo "<tr class=\"server4 $hide3\"><td>"._('DNSv4 server').":</td><td><input type=\"text\" name=\"SERVER4\" class=\"narrow\" autocomplete=\"off\" spellcheck=\"false\" value=\"$server4\"></td></tr>";
|
||||
echo "<tr><td colspan=\"2\"> </td></tr>";
|
||||
echo "<tr><td>"._('IPv6 address assignment').":</td><td><select name=\"DHCP6\" onclick=\"showDHCP(this.value,6)\">";
|
||||
echo mk_option($dhcp6, '', _('None'));
|
||||
echo mk_option($dhcp6, 'yes', _('Automatic'));
|
||||
echo mk_option($dhcp6, 'no', _('Static'));
|
||||
echo "</select></td></tr>";
|
||||
echo "<tr class=\"static6 $hide4\"><td>"._('IPv6 address').":</td><td><input type=\"text\" name=\"IP6\" class=\"narrow\" maxlength=\"39\" autocomplete=\"off\" spellcheck=\"false\" value=\"$ip6\">/<input type=\"number\" min=\"1\" max=\"128\" maxlength=\"3\" name=\"MASK6\" class=\"slim\" value=\"$mask6\"></td></tr>";
|
||||
echo "<tr class=\"static6 $hide4\"><td>"._('IPv6 default gateway').":</td><td><input type=\"text\" name=\"GATEWAY6\" class=\"narrow\" maxlength=\"39\" autocomplete=\"off\" spellcheck=\"false\" value=\"$gw6\"></td></tr>";
|
||||
echo "<tr class=\"dns6 $hide5\"><td>"._('IPv6 DNS assignment').":</td><td><select name=\"DNS6\" onclick=\"showDNS(this.value,6)\">";
|
||||
echo mk_option($dns6, "no", _("Automatic"));
|
||||
echo mk_option($dns6, "yes", _("Static"));
|
||||
echo "</select></td></tr>";
|
||||
echo "<tr class=\"server6 $hide6\"><td>"._('DNSv6 server').":</td><td><input type=\"text\" name=\"SERVER6\" class=\"narrow\" autocomplete=\"off\" spellcheck=\"false\" value=\"$server6\"></td></tr>";
|
||||
echo "<tr><td colspan=\"2\"> </td></tr>";
|
||||
echo "</table>";
|
||||
echo "</form>";
|
||||
break;
|
||||
case 'forget':
|
||||
$ssid = rawurldecode($_POST['ssid']);
|
||||
if ($wifi[$ssid]['GROUP'] == 'active') exec("/etc/rc.d/rc.wireless stop &>/dev/null &");
|
||||
unset($wifi[$ssid]);
|
||||
saveWifi();
|
||||
break;
|
||||
}
|
||||
?>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -39,13 +39,16 @@ 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";
|
||||
@@ -53,11 +56,13 @@ function parse_plugin_cfg($plugin, $sections=false, $scanner=INI_SCANNER_NORMAL)
|
||||
$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";
|
||||
if ($text) file_put_contents($cron, $text); else @unlink($cron);
|
||||
exec("/usr/local/sbin/update_cron");
|
||||
}
|
||||
|
||||
function agent_fullname($agent, $state) {
|
||||
switch ($state) {
|
||||
case 'enabled' : return "/boot/config/plugins/dynamix/notifications/agents/$agent";
|
||||
@@ -65,11 +70,13 @@ function agent_fullname($agent, $state) {
|
||||
default : return $agent;
|
||||
}
|
||||
}
|
||||
|
||||
function get_plugin_attr($attr, $file) {
|
||||
global $docroot;
|
||||
exec("$docroot/plugins/dynamix.plugin.manager/scripts/plugin ".escapeshellarg($attr)." ".escapeshellarg($file), $result, $error);
|
||||
if ($error===0) return $result[0];
|
||||
}
|
||||
|
||||
function plugin_update_available($plugin, $os=false) {
|
||||
$local = get_plugin_attr('version', "/var/log/plugins/$plugin.plg");
|
||||
$remote = get_plugin_attr('version', "/tmp/plugins/$plugin.plg");
|
||||
@@ -80,24 +87,30 @@ function plugin_update_available($plugin, $os=false) {
|
||||
if (version_compare($server, $unraid, '>=')) return $remote;
|
||||
}
|
||||
}
|
||||
|
||||
function _var(&$name, $key=null, $default='') {
|
||||
return is_null($key) ? ($name ?? $default) : ($name[$key] ?? $default);
|
||||
}
|
||||
|
||||
function celsius($temp) {
|
||||
return round(($temp-32)*5/9);
|
||||
}
|
||||
|
||||
function fahrenheit($temp) {
|
||||
return round(9/5*$temp)+32;
|
||||
}
|
||||
|
||||
function displayTemp($temp) {
|
||||
global $display;
|
||||
return (is_numeric($temp) && _var($display,'unit')=='F') ? fahrenheit($temp) : $temp;
|
||||
}
|
||||
|
||||
function get_value(&$name, $key, $default) {
|
||||
global $var;
|
||||
$value = $name[$key] ?? -1;
|
||||
return $value!==-1 ? $value : ($var[$key] ?? $default);
|
||||
}
|
||||
|
||||
function get_ctlr_options(&$type, &$disk) {
|
||||
if (!$type) return;
|
||||
$ports = [];
|
||||
@@ -106,12 +119,15 @@ function get_ctlr_options(&$type, &$disk) {
|
||||
if (isset($disk['smPort3'])) $ports[] = $disk['smPort3'];
|
||||
$type .= ($ports ? ','.implode($disk['smGlue'] ?? ',',$ports) : '');
|
||||
}
|
||||
|
||||
function port_name($port) {
|
||||
return substr($port,-2)!='n1' ? $port : substr($port,0,-2);
|
||||
}
|
||||
|
||||
function exceed($value, $limit, $top=100) {
|
||||
return is_numeric($value) && $limit>0 ? ($value>$limit && $value<=$top) : false;
|
||||
}
|
||||
|
||||
function ipaddr($ethX='eth0', $prot=4) {
|
||||
global $$ethX;
|
||||
switch (_var($$ethX,'PROTOCOL:0')) {
|
||||
@@ -128,16 +144,20 @@ function ipaddr($ethX='eth0', $prot=4) {
|
||||
return _var($$ethX,'IPADDR:0');
|
||||
}
|
||||
}
|
||||
|
||||
function no_tilde($name) {
|
||||
global $_tilde_ ,$_proxy_;
|
||||
return str_replace($_tilde_,$_proxy_,$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) {
|
||||
@@ -145,11 +165,13 @@ function native($name, $full=0) {
|
||||
case 1: return strpos($name,$_tilde_)!==false ? "$_arrow_ ".explode($_tilde_,$name)[1] : $name;
|
||||
}
|
||||
}
|
||||
|
||||
function isSubpool($name) {
|
||||
global $subpools, $_tilde_;
|
||||
$subpool = my_explode($_tilde_,$name)[1];
|
||||
return in_array($subpool,$subpools) ? $subpool : false;
|
||||
}
|
||||
|
||||
function get_nvme_info($device, $info) {
|
||||
switch ($info) {
|
||||
case 'temp':
|
||||
@@ -167,15 +189,18 @@ function get_nvme_info($device, $info) {
|
||||
return exec("smartctl -c /dev/$device 2>/dev/null | grep -Pom1 '^ *$state [+-] +\K[^W]+'");
|
||||
}
|
||||
}
|
||||
|
||||
// convert strftime to date format
|
||||
function my_date($fmt, $time) {
|
||||
$legacy = ['%c' => 'D j M Y h:i A','%A' => 'l','%Y' => 'Y','%B' => 'F','%e' => 'j','%d' => 'd','%m' => 'm','%I' => 'h','%H' => 'H','%M' => 'i','%S' => 's','%p' => 'a','%R' => 'H:i', '%F' => 'Y-m-d', '%T' => 'H:i:s'];
|
||||
return date(strtr($fmt,$legacy), $time);
|
||||
}
|
||||
|
||||
// ensure params passed to logger are properly escaped
|
||||
function my_logger($message, $logger='webgui') {
|
||||
exec('logger -t '.escapeshellarg($logger).' -- '.escapeshellarg($message));
|
||||
}
|
||||
|
||||
// Original PHP code by Chirp Internet: www.chirpinternet.eu
|
||||
// Please acknowledge use of this code by including this header.
|
||||
// https://www.the-art-of-web.com/php/http-get-contents/
|
||||
@@ -226,6 +251,7 @@ function http_get_contents(string $url, array $opts = [], array &$getinfo = NULL
|
||||
curl_close($ch);
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect network connectivity via Network Connectivity Status Indicator
|
||||
* @return bool
|
||||
@@ -235,4 +261,10 @@ function check_network_connectivity(): bool {
|
||||
$out = http_get_contents($url);
|
||||
return ($out=="Microsoft NCSI");
|
||||
}
|
||||
|
||||
function lan_port($port, $state=false) {
|
||||
$system = '/sys/class/net';
|
||||
$exist = file_exists("$system/$port");
|
||||
return !$state ? $exist : ($exist ? file_get_contents("$system/$port/carrier") : false);
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$ssl = '/etc/rc.d/rc.ssl.input';
|
||||
if (is_readable($ssl)) extract(parse_ini_file($ssl));
|
||||
|
||||
// encrypt username and password before saving (if existing)
|
||||
if (!empty($_POST['USERNAME']) && isset($cipher,$key,$iv)) $_POST['USERNAME'] = openssl_encrypt($_POST['USERNAME'],$cipher,$key,0,$iv);
|
||||
if (!empty($_POST['PASSWORD']) && isset($cipher,$key,$iv)) $_POST['PASSWORD'] = openssl_encrypt($_POST['PASSWORD'],$cipher,$key,0,$iv);
|
||||
|
||||
// update active wifi selection
|
||||
foreach ($keys as $key => $val) if (isset($val['GROUP'])) $keys[$key]['GROUP'] = 'saved';
|
||||
$keys[$section]['GROUP'] = 'active';
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
@@ -50,7 +50,8 @@ function update_translation($locale) {
|
||||
}
|
||||
function ports() {
|
||||
global $net;
|
||||
exec("ls --indicator-style=none $net|grep -Po '^(lo|(bond|eth)\d+)$'",$ports);
|
||||
exec("ls --indicator-style=none $net|grep -Po '^(bond|eth|wlan)\d+$'",$ports);
|
||||
$ports[] = 'lo';
|
||||
return $ports;
|
||||
}
|
||||
|
||||
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/publish.php";
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = '';
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
function update_translation($locale) {
|
||||
global $docroot,$language;
|
||||
$language = [];
|
||||
if ($locale) {
|
||||
$text = "$docroot/languages/$locale/translations.txt";
|
||||
if (file_exists($text)) {
|
||||
$store = "$docroot/languages/$locale/translations.dot";
|
||||
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
|
||||
$language = unserialize(file_get_contents($store));
|
||||
}
|
||||
$text = "$docroot/languages/$locale/dashboard.txt";
|
||||
if (file_exists($text)) {
|
||||
$store = "$docroot/languages/$locale/dashboard.dot";
|
||||
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
|
||||
$language = array_merge($language,unserialize(file_get_contents($store)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$echo = [];
|
||||
$wlan0 = '/sys/class/net/wlan0/carrier';
|
||||
$ini = '/var/local/emhttp/wireless.ini';
|
||||
while (true) {
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
if (_var($display,'locale') != $locale_init) {
|
||||
$locale_init = _var($display,'locale');
|
||||
update_translation($locale_init);
|
||||
}
|
||||
if (file_exists($ini) && file_exists($wlan0)) {
|
||||
$up = file_get_contents($wlan0)==1;
|
||||
$echo['color'] = $up ? 'blue-text' : 'red-text';
|
||||
$echo['title'] = $up ? _('WiFi connected') : _('WiFi disconnected');
|
||||
} else {
|
||||
$echo['color'] = 'grey-text';
|
||||
$echo['title'] = _('No active WiFi');
|
||||
}
|
||||
publish('wlan0',json_encode($echo));
|
||||
sleep(3);
|
||||
}
|
||||
?>
|
||||
@@ -2,14 +2,12 @@
|
||||
nets=()
|
||||
while IFS='\n' read -r net; do
|
||||
net=${net%/*}
|
||||
net4=$(ip -br -4 addr show to $net 2>/dev/null|awk '$1 !~ "^shim" {print $1}'|tr '\n' ','|sed 's/,$//')
|
||||
net4=$(ip -br -4 addr show scope global to $net 2>/dev/null | awk '$1 !~ "^shim" {print $1}'|tr '\n' ',' | sed 's/,$//')
|
||||
[[ -n $net4 ]] && nets+=("$net4 = $net;")
|
||||
done <<< $(ip -br -4 addr|awk '/^(br|bond|eth|wg)[0-9]+(\.[0-9]+)?/ {print $3}'|uniq -d)
|
||||
done <<< $(ip -br -4 addr show scope global | awk '/^(br|bond|eth|wlan|wg)[0-9]+(\.[0-9]+)?/ {print $3}' | uniq -d)
|
||||
|
||||
while IFS=$'\n' read -r net; do
|
||||
net=${net%/*}
|
||||
net6=$(ip -br -6 addr show to $net 2>/dev/null|awk '$1 !~ "^shim" {print $1}'|tr '\n' ','|sed 's/,$//')
|
||||
net6=$(ip -br -6 addr show scope global -temporary -deprecated to $net 2>/dev/null | awk '$1 !~ "^shim" {print $1}'|tr '\n' ',' | sed 's/,$//')
|
||||
[[ -n $net6 ]] && nets+=("$net6 = $net;")
|
||||
done <<< $(ip -br -6 addr|awk '/^(br|bond|eth|wg)[0-9]+(\.[0-9]+)?/ && $3 !~ "^fe80" {print $3}'|uniq -d)
|
||||
|
||||
[[ -n $nets ]] && echo "<i class='fa fa-warning' style='margin-right:8px'></i>${nets[@]}"|sed 's/;$//'
|
||||
done <<< $(ip -br -6 addr show scope global -temporary -deprecated | awk '/^(br|bond|eth|wlan|wg)[0-9]+(\.[0-9]+)?/ {print $3}' | uniq -d)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -19,13 +19,19 @@ require_once "$docroot/webGui/include/Wrappers.php";
|
||||
if ($argc == 1) exit;
|
||||
|
||||
$set = $ifname = $argv[1];
|
||||
$run = $set != 'none';
|
||||
$run = $set !== 'none';
|
||||
$dns = $set === 'renew';
|
||||
$ini = parse_ini_file('/var/local/emhttp/network.ini',true); ksort($ini,SORT_NATURAL);
|
||||
$cfg = '/boot/config/network.cfg';
|
||||
|
||||
function port($x) {
|
||||
$sys = "/sys/class/net";
|
||||
return file_exists("$sys/br{$x}") ? "br${x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
|
||||
}
|
||||
|
||||
function update_wireguard($ifname) {
|
||||
if (!in_array($ifname,['br0','bond0','eth0'])) return;
|
||||
$nic = file_exists('/sys/class/net/br0') ? 'br0' : (file_exists('/sys/class/net/bond0') ? 'bond0' : 'eth0');
|
||||
$nic = port(0);
|
||||
exec("wg show interfaces|tr ' ' '\n'",$active);
|
||||
foreach (glob("/etc/wireguard/*.conf",GLOB_NOSORT) as $wg) {
|
||||
$vtun = basename($wg,'.conf');
|
||||
@@ -38,6 +44,7 @@ function update_wireguard($ifname) {
|
||||
if (in_array($vtun,$active)) exec("wg-quick down $vtun; sleep 1; wg-quick up $vtun");
|
||||
}
|
||||
}
|
||||
|
||||
function ifname($name) {
|
||||
global $old;
|
||||
if (!$name) return;
|
||||
@@ -47,10 +54,12 @@ function ifname($name) {
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
function bond_nics(&$bond,$nic) {
|
||||
$bond['BONDNICS'] = str_replace(',',' ',$bond['BONDNICS']);
|
||||
return explode(' ',preg_replace("/$nic ?/","",$bond['BONDNICS']));
|
||||
}
|
||||
|
||||
function bridge_nics(&$bridge,$nic) {
|
||||
$bridge['BRNICS'] = str_replace(',',' ',$bridge['BRNICS']);
|
||||
return explode(' ',preg_replace("/$nic ?/","",$bridge['BRNICS']));
|
||||
@@ -59,29 +68,36 @@ function bridge_nics(&$bridge,$nic) {
|
||||
// stop interface with existing (old) configuration
|
||||
// don't execute when only interface description has changed
|
||||
if ($run) {
|
||||
$old = [];
|
||||
if (file_exists($cfg)) {
|
||||
$old = parse_ini_string(preg_replace(['/^#/m',"/\r/m"],[';',''],file_get_contents($cfg)));
|
||||
if (isset($old['SYSNICS'])) {
|
||||
// new syntax
|
||||
$ifname = ifname($set);
|
||||
} else {
|
||||
// legacy syntax
|
||||
if ($set=='eth0') $ifname = $old['BRIDGING']=='yes' ? ($old['BRNAME'] ?? 'br0') : ($old['BONDING']=='yes' ? ($old['BONDNAME'] ?? 'bond0') : $set);
|
||||
if ($dns) {
|
||||
$cmd = 'start_renew';
|
||||
$ifname = port(0);
|
||||
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_stop_renew")." >/dev/null");
|
||||
} else {
|
||||
$cmd = 'start';
|
||||
$old = [];
|
||||
if (file_exists($cfg)) {
|
||||
$old = parse_ini_string(preg_replace(['/^#/m',"/\r/m"],[';',''],file_get_contents($cfg)));
|
||||
if (isset($old['SYSNICS'])) {
|
||||
// new syntax
|
||||
$ifname = ifname($set);
|
||||
} else {
|
||||
// legacy syntax
|
||||
if ($set=='eth0') $ifname = $old['BRIDGING']=='yes' ? ($old['BRNAME'] ?? 'br0') : ($old['BONDING']=='yes' ? ($old['BONDNAME'] ?? 'bond0') : $set);
|
||||
}
|
||||
}
|
||||
}
|
||||
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_stop")." >/dev/null");
|
||||
if ($ini[$set]['BONDING']=='yes') {
|
||||
// release additional NICs in bond
|
||||
foreach (bond_nics($ini[$set],$set) as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
if ($nic && $nic!=$ifname) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
||||
}
|
||||
} elseif ($ini[$set]['BRIDGING']=='yes') {
|
||||
// release additional NICs in bridge
|
||||
foreach (bridge_nics($ini[$set],$set) as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
if ($nic && $nic!=$ifname) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
||||
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_stop")." >/dev/null");
|
||||
if ($ini[$set]['BONDING']=='yes') {
|
||||
// release additional NICs in bond
|
||||
foreach (bond_nics($ini[$set],$set) as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
if ($nic && $nic!=$ifname) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
||||
}
|
||||
} elseif ($ini[$set]['BRIDGING']=='yes') {
|
||||
// release additional NICs in bridge
|
||||
foreach (bridge_nics($ini[$set],$set) as $nic) {
|
||||
if (isset($old['SYSNICS'])) $nic = ifname($nic);
|
||||
if ($nic && $nic!=$ifname) exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$nic}_stop")." >/dev/null");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -127,14 +143,14 @@ foreach ($ini as $name => $port) {
|
||||
$i++;
|
||||
}
|
||||
$new[] = "SYSNICS=\"$i\"";
|
||||
|
||||
file_put_contents($cfg,implode("\r\n",$new)."\r\n");
|
||||
|
||||
// start interface with updated (new) configuration
|
||||
// don't execute when only interface description has changed
|
||||
if ($run) {
|
||||
exec("/etc/rc.d/rc.inet1 {$ifname}_start &>/dev/null");
|
||||
exec("/usr/local/sbin/create_network_ini $ifname &>/dev/null &");
|
||||
update_wireguard($ifname);
|
||||
exec("/etc/rc.d/rc.inet1 ".escapeshellarg("{$ifname}_{$cmd}")." >/dev/null");
|
||||
exec("/usr/local/sbin/create_network_ini ".escapeshellarg($ifname)." &>/dev/null &");
|
||||
if (!$dns) update_wireguard($ifname);
|
||||
}
|
||||
exit(0);
|
||||
?>
|
||||
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2025, Lime Technology
|
||||
* Copyright 2012-2025, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
|
||||
require_once "$docroot/plugins/dynamix/include/Wrappers.php";
|
||||
|
||||
$arg = $argv[1] ?? '';
|
||||
$state = $arg ? 'saved' : 'active';
|
||||
$ini = '/var/local/emhttp/wireless.ini';
|
||||
$cfg = '/boot/config/wireless.cfg';
|
||||
$wifi = is_file($cfg) ? (array)parse_ini_file($cfg,true) : [];
|
||||
$port = array_key_first($wifi);
|
||||
$text = ["PORT=\"$port\""];
|
||||
|
||||
if ($arg == 'yes') {
|
||||
exec("/etc/rc.d/rc.wireless start &>/dev/null &");
|
||||
} elseif ($arg == 'no') {
|
||||
exec("/etc/rc.d/rc.wireless stop");
|
||||
exec("$docroot/webGui/scripts/update_services 5");
|
||||
} else {
|
||||
foreach ($wifi as $network => $block) {
|
||||
if ($network == $port) continue;
|
||||
if ($block['GROUP'] == $state && (!$arg || $arg == $network)) {
|
||||
$text[] = "SSID=\"$network\"";
|
||||
unset($block['GROUP']);
|
||||
foreach ($block as $key => $value) $text[] = "$key=\"$value\"";
|
||||
}
|
||||
}
|
||||
if (count($text)>2) {
|
||||
exec("/etc/rc.d/rc.wireless stop");
|
||||
file_put_contents_atomic($ini,implode("\n",$text)."\n");
|
||||
exec("/etc/rc.d/rc.wireless join &>/dev/null &");
|
||||
exec("$docroot/webGui/scripts/update_services 20");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -1 +1,2 @@
|
||||
span.ntp{margin-left:40px}
|
||||
div.extra,span.ipv4,span.ipv6,span.mac,span#noports{display:none}
|
||||
select,input[type=text]{margin-right:40px}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
.uplift{margin-top:-30px!important}
|
||||
@@ -0,0 +1 @@
|
||||
.uplift{margin-top:-30px!important}
|
||||
@@ -3,10 +3,11 @@ span.blue{color:#00529B}
|
||||
span.green{color:#4F8A10}
|
||||
span.vshift{margin-top:0!important}
|
||||
input.gap{margin-right:6px}
|
||||
input.form{font-size:1rem;padding:5px 10px;margin-left:10px}
|
||||
input.form{font-size:1rem;padding:5px 10px;margin:0 0 0 10px}
|
||||
div.shade-white{background-color:#ededed;margin-top:10px;padding:8px 0 3px 0}
|
||||
div.shade-black{background-color:#212121;margin-top:10px;padding:8px 0 3px 0}
|
||||
div.shade-azure{background-color:#edeaef;margin-top:10px;padding:8px 0 3px 0}
|
||||
div.shade-gray{background-color:#121510;margin-top:10px;padding:8px 0 3px 0}
|
||||
select.slim{min-width:47px;margin-left:4px}
|
||||
input.slim{width:32px;margin-left:8px}
|
||||
.hide{display:none}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
.mybar{height:30px;line-height:30px;margin-bottom:24px;border:none;border-radius:3px;box-shadow:inset 0 1px 0 rgba(255,255,255,.5)}
|
||||
.mybar.left{float:left}
|
||||
.whitebar{background:-webkit-radial-gradient(#c7c7c7,#eeeeee);background:linear-gradient(#c7c7c7,#eeeeee)}
|
||||
img.left{float:left;margin-right:5px}
|
||||
img.top{margin-top:-3px}
|
||||
div.leftbar{float:left;line-height:16px;width:16%}
|
||||
div.rightbar{float:right;line-height:16px;width:12%}
|
||||
.inside{float:left;width:30px;margin-right:6px;clear:both}
|
||||
.graph1{float:left;margin:0}
|
||||
.graph2{float:left;margin:0 0 40px 0}
|
||||
.graph2.last{margin-bottom:0}
|
||||
.graph3{float:left;margin:20px 6px 20px 0}
|
||||
.graph3.last{margin-right:0}
|
||||
@@ -0,0 +1 @@
|
||||
input.narrow:focus,input.slim:focus{background-color:#edeaef;box-shadow:none;outline:none;border:none;border:1px solid #0072c6}
|
||||
@@ -0,0 +1 @@
|
||||
input.narrow:focus,input.slim:focus{background-color:#262626;box-shadow:none;outline:none;border:none;border-bottom:1px solid #e5e5e5}
|
||||
@@ -0,0 +1 @@
|
||||
input.narrow:focus,input.slim:focus{background-color:#121510;box-shadow:none;outline:none;border:none;border:1px solid #0072c6}
|
||||
@@ -0,0 +1 @@
|
||||
input.narrow:focus,input.slim:focus{background-color:#e8e8e8;box-shadow:none;outline:none;border:none;border-bottom:1px solid #1c1b1b}
|
||||
@@ -0,0 +1,8 @@
|
||||
.wifi{display:inline-block;width:300px}
|
||||
.hide{display:none}
|
||||
i.hand{cursor:pointer;text-decoration:none}
|
||||
input.form{font-size:1rem;padding:5px 10px;margin:0}
|
||||
input[type=button].form{margin-left:20px}
|
||||
table.swal{text-align:left;font-size:1.2rem}
|
||||
table.swal td:nth-child(1){width:42%;text-align:right;padding-right:30px}
|
||||
#showPass{cursor:pointer;margin-left:10px}
|
||||
@@ -0,0 +1 @@
|
||||
.uplift{margin-top:-30px!important}
|
||||
@@ -0,0 +1 @@
|
||||
.uplift{margin-top:-30px!important}
|
||||
@@ -60,8 +60,8 @@ div.title span.right{font-size:1.4rem;padding-top:2px;padding-right:10px;float:r
|
||||
div.title span img{padding-right:4px}
|
||||
div.title.shift{margin-top:-30px}
|
||||
#menu{position:absolute;top:90px;left:0;right:0;display:grid;grid-template-columns:auto max-content;z-index:101}
|
||||
.nav-tile{height:4rem;line-height:4rem;padding:0;margin:0;font-size:1.2rem;letter-spacing:1.8px;background-color:#f2f2f2;white-space:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}
|
||||
.nav-tile::-webkit-scrollbar{height:5px}
|
||||
.nav-tile{height:4rem;line-height:4rem;padding:0;margin:0;font-size:1.2rem;letter-spacing:1.8px;background-color:#f2f2f2;white-space:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:4px}
|
||||
.nav-tile::-webkit-scrollbar{height:4px}
|
||||
.nav-tile.right{text-align:right}
|
||||
.nav-item,.nav-user{position:relative;display:inline-block;text-align:center;margin:0}
|
||||
.nav-item a{min-width:0}
|
||||
@@ -204,8 +204,8 @@ a.list{text-decoration:none;color:inherit}
|
||||
div.content{position:absolute;top:0;left:0;width:100%;padding-bottom:30px;z-index:-1;clear:both}
|
||||
div.content.shift{margin-top:1px}
|
||||
label+.content{margin-top:86px}
|
||||
div.tabs{position:relative;margin:130px 0 0 0}
|
||||
div.tab{float:left;margin-top:30px}
|
||||
div.tabs{position:relative;margin:120px 0 0 0}
|
||||
div.tab{float:left;margin-top:32px}
|
||||
div.tab input[id^="tab"]{display:none}
|
||||
div.tab [type=radio]+label:hover{background-color:transparent;border:1px solid #ff8c2f;border-bottom:none;cursor:pointer;opacity:1}
|
||||
div.tab [type=radio]:checked+label{cursor:default;background-color:transparent;border:1px solid #ff8c2f;border-bottom:none;opacity:1}
|
||||
|
||||
@@ -60,8 +60,8 @@ div.title span.right{font-size:1.4rem;padding-top:2px;padding-right:10px;float:r
|
||||
div.title span img{padding-right:4px}
|
||||
div.title.shift{margin-top:-30px}
|
||||
#menu{position:absolute;top:90px;left:0;right:0;display:grid;grid-template-columns:auto max-content;z-index:101}
|
||||
.nav-tile{height:4rem;line-height:4rem;padding:0;margin:0;font-size:1.2rem;letter-spacing:1.8px;background-color:#1c1b1b;white-space:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:thin}
|
||||
.nav-tile::-webkit-scrollbar{height:5px}
|
||||
.nav-tile{height:4rem;line-height:4rem;padding:0;margin:0;font-size:1.2rem;letter-spacing:1.8px;background-color:#1c1b1b;white-space:nowrap;overflow-x:auto;overflow-y:hidden;scrollbar-width:4px}
|
||||
.nav-tile::-webkit-scrollbar{height:4px}
|
||||
.nav-tile.right{text-align:right}
|
||||
.nav-item,.nav-user{position:relative;display:inline-block;text-align:center;margin:0}
|
||||
.nav-item a{min-width:0}
|
||||
@@ -204,8 +204,8 @@ a.list{text-decoration:none;color:inherit}
|
||||
div.content{position:absolute;top:0;left:0;width:100%;padding-bottom:30px;z-index:-1;clear:both}
|
||||
div.content.shift{margin-top:1px}
|
||||
label+.content{margin-top:86px}
|
||||
div.tabs{position:relative;margin:130px 0 0 0}
|
||||
div.tab{float:left;margin-top:30px}
|
||||
div.tabs{position:relative;margin:120px 0 0 0}
|
||||
div.tab{float:left;margin-top:32px}
|
||||
div.tab input[id^="tab"]{display:none}
|
||||
div.tab [type=radio]+label:hover{background-color:transparent;border:1px solid #ff8c2f;border-bottom:none;cursor:pointer;opacity:1}
|
||||
div.tab [type=radio]:checked+label{cursor:default;background-color:transparent;border:1px solid #ff8c2f;border-bottom:none;opacity:1}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
.upgrade_notice.done{color:#4f8a10;background-color:#dff2bf;border-color:#4f8a10}
|
||||
.upgrade_notice.alert{color:#f0000c;background-color:#ff9e9e;border-color:#f0000c}
|
||||
.upgrade_notice i{float:right;cursor:pointer}
|
||||
.back_to_top{display:none;position:fixed;bottom:30px;right:12px;color:#e22828;font-size:2.5rem;z-index:999}
|
||||
.move_to_end{display:none;position:fixed;bottom:24px;right:12px;color:#e22828;font-size:2.5rem;z-index:999}
|
||||
.back_to_top{display:none;position:fixed;bottom:24px;right:40px;color:#e22828;font-size:2.5rem;z-index:999}
|
||||
span.big.blue-text{cursor:pointer}
|
||||
span.strong.tour{margin-left:5px;padding-left:0}
|
||||
i.abortOps{font-size:2rem;float:right;margin-right:20px;margin-top:8px;cursor:pointer}
|
||||
pre#swalbody p{margin-block-end:1em}
|
||||
span#wlan0{float:right;margin-right:10px;cursor:pointer}
|
||||
@@ -26,7 +26,7 @@ pre#swaltext{text-align:left;margin:0;padding:0;height:650px;white-space:normal;
|
||||
.sweet-alert .sa-input-error::before{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}
|
||||
.sweet-alert .sa-input-error::after{-webkit-transform:rotate(45deg);transform:rotate(45deg)}
|
||||
.sweet-alert .sa-input-error.show{opacity:1;-webkit-transform:scale(1);transform:scale(1)}
|
||||
.sweet-alert input[type=text]{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d7d7d7;height:43px;margin-top:10px;margin-bottom:17px;font-size:1.8rem;box-shadow:inset 0px 1px 1px rgba(0, 0, 0, 0.06);padding:0 12px;display:none;-webkit-transition:all 0.3s;transition:all 0.3s}
|
||||
.sweet-alert fieldset input[type=text]{width:100%;box-sizing:border-box;border-radius:3px;border:1px solid #d7d7d7;height:43px;margin-top:10px;margin-bottom:17px;font-size:1.8rem;box-shadow:inset 0px 1px 1px rgba(0, 0, 0, 0.06);padding:0 12px;display:none;-webkit-transition:all 0.3s;transition:all 0.3s}
|
||||
.sweet-alert input:focus{outline:none;box-shadow:0px 0px 3px #c4e6f5;border:1px solid #b4dbed}
|
||||
.sweet-alert input:focus::-moz-placeholder{transition:opacity 0.3s 0.03s ease;opacity:0.5}
|
||||
.sweet-alert input:focus:-ms-input-placeholder{transition:opacity 0.3s 0.03s ease;opacity:0.5}
|
||||
|
||||
+2
-2
@@ -39,13 +39,13 @@ fi
|
||||
if grep -q quota /etc/fstab ; then
|
||||
if [[ -x /sbin/quotaoff ]]; then
|
||||
log "Turning off filesystem quotas."
|
||||
run quotaoff -a
|
||||
run /sbin/quotaoff -a
|
||||
fi
|
||||
fi
|
||||
|
||||
# Try to turn off accounting:
|
||||
if [[ -x /sbin/accton && -r /var/log/pacct ]]; then
|
||||
accton off
|
||||
/sbin/accton off
|
||||
fi
|
||||
|
||||
# Run any local shutdown scripts:
|
||||
|
||||
+12
-2
@@ -11,7 +11,7 @@
|
||||
# Heavily modified by Patrick Volkerding <volkerdi@slackware.com>
|
||||
#
|
||||
# LimeTech - modified for Unraid OS
|
||||
# Bergware - modified for Unraid OS, October 2023
|
||||
# Bergware - modified for Unraid OS, December 2024
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
@@ -83,6 +83,11 @@ if [[ -x /etc/rc.d/rc.inet1 ]]; then
|
||||
/etc/rc.d/rc.inet1
|
||||
fi
|
||||
|
||||
# Initialize the wireless networking.
|
||||
if [[ -x /etc/rc.d/rc.wireless ]]; then
|
||||
/etc/rc.d/rc.wireless start
|
||||
fi
|
||||
|
||||
# Start D-Bus:
|
||||
if [[ -x /etc/rc.d/rc.messagebus ]]; then
|
||||
/etc/rc.d/rc.messagebus start
|
||||
@@ -108,6 +113,11 @@ fi
|
||||
# Mount any additional filesystem types that haven't already been mounted:
|
||||
mount -a -v 2>/dev/null | grep -v -e "already mounted" -e "ignored" | cut -f 1 -d : | tr -d ' ' | while read DEV; do mount | grep "$DEV "; done
|
||||
|
||||
# Start the Precision Time Protocol daemon:
|
||||
if [[ -x /etc/rc.d/rc.ptpd ]]; then
|
||||
/etc/rc.d/rc.ptpd start
|
||||
fi
|
||||
|
||||
# Start the Network Time Protocol daemon:
|
||||
if [[ -x /etc/rc.d/rc.ntpd ]]; then
|
||||
/etc/rc.d/rc.ntpd start
|
||||
@@ -189,7 +199,7 @@ fi
|
||||
# because the log file can get VERY large.
|
||||
if [[ -x /sbin/accton && -r /var/log/pacct ]]; then
|
||||
chmod 640 /var/log/pacct
|
||||
accton /var/log/pacct
|
||||
/sbin/accton /var/log/pacct
|
||||
fi
|
||||
|
||||
# Start crond (Dillon's crond):
|
||||
|
||||
+1
-1
@@ -100,7 +100,7 @@ FREQ=0
|
||||
if [[ -r /etc/default/adjtimex ]]; then
|
||||
. /etc/default/adjtimex
|
||||
fi
|
||||
if adjtimex --tick $TICK --frequency $FREQ; then
|
||||
if /sbin/adjtimex --tick $TICK --frequency $FREQ; then
|
||||
log "Setting the system clock rate: adjtimex --tick $TICK --frequency $FREQ"
|
||||
else
|
||||
log "Failed to set system clock with adjtimex, possibly invalid parameters? (TICK=$TICK FREQ=$FREQ)"
|
||||
|
||||
@@ -53,18 +53,18 @@ disable(){
|
||||
|
||||
# when starting avahidaemon, add name.local to the hosts file
|
||||
add_local_to_hosts(){
|
||||
local old new
|
||||
old="^127\.0\.0\.1.*"
|
||||
new="127.0.0.1 $NAME $NAME.local localhost"
|
||||
sed -i "s/$old/$new/gm;t" $HOSTS
|
||||
local OLD="^127\.0\.0\.1.*"
|
||||
local NEW="127.0.0.1 $NAME $NAME.local localhost"
|
||||
sed -i "s/$OLD/$NEW/gm;t" $HOSTS
|
||||
return 0
|
||||
}
|
||||
|
||||
# when stopping avahidaemon, remove name.local from the hosts file
|
||||
remove_local_from_hosts(){
|
||||
local old new
|
||||
old="^127\.0\.0\.1.*"
|
||||
new="127.0.0.1 $NAME localhost"
|
||||
sed -i "s/$old/$new/gm;t" $HOSTS
|
||||
local OLD="^127\.0\.0\.1.*"
|
||||
local NEW="127.0.0.1 $NAME localhost"
|
||||
sed -i "s/$OLD/$NEW/gm;t" $HOSTS
|
||||
return 0
|
||||
}
|
||||
|
||||
avahid_running(){
|
||||
|
||||
@@ -54,7 +54,7 @@ case "$1" in
|
||||
echo "$DAEMON running"
|
||||
else
|
||||
echo "$DAEMON not running"
|
||||
if [ -f $PID ]; then
|
||||
if [[ -f $PID ]]; then
|
||||
rm -f $PID
|
||||
fi
|
||||
fi
|
||||
|
||||
+15
-22
@@ -10,7 +10,7 @@
|
||||
# VMs, bare metal, OpenStack clusters, public clouds and more.
|
||||
#
|
||||
# LimeTech - modified for Unraid OS
|
||||
# Bergware - modified for Unraid OS, October 2023
|
||||
# Bergware - modified for Unraid OS, January 2025
|
||||
|
||||
DAEMON="Docker daemon"
|
||||
UNSHARE="/usr/bin/unshare"
|
||||
@@ -314,7 +314,7 @@ docker_network_start(){
|
||||
fi
|
||||
# add auto defined networks
|
||||
SUBNET=; GATEWAY=; SERVER=; RANGE=;
|
||||
IPV4=$(ip -br -4 addr show $NETWORK | awk '{print $3;exit}')
|
||||
IPV4=$(ip -4 -br addr show $NETWORK scope global | awk '{print $3;exit}')
|
||||
if [[ -n $IPV4 ]]; then
|
||||
SUBNET=$(ip -4 route show $IPV4 dev $NETWORK | awk '{print $1;exit}')
|
||||
SERVER=${IPV4%/*}
|
||||
@@ -323,16 +323,12 @@ docker_network_start(){
|
||||
RANGE=${!DHCP}
|
||||
GATEWAY=$(ip -4 route show default dev $NETWORK | awk '{print $3;exit}')
|
||||
fi
|
||||
SUBNET6=; GATEWAY6=; SERVER6=; RANGE6=;
|
||||
IPV6=$(ip -br -6 addr show $NETWORK scope global mngtmpaddr|awk '{print $3;exit}')
|
||||
[[ -z $IPV6 ]] && IPV6=$(ip -br -6 addr show $NETWORK scope global permanent|awk '{print $3;exit}')
|
||||
SUBNET6=; GATEWAY6=; SERVER6=;
|
||||
IPV6=$(ip -6 -br addr show $NETWORK scope global -temporary -deprecated | awk '{print $3;exit}')
|
||||
if [[ -n $IPV6 ]]; then
|
||||
# get IPV6 subnet, preset to /64 if single host address is given
|
||||
[[ ${IPV6#*/} == 128 ]] && SUBNET6=$(echo $IPV6 | sed -r 's/^([^:]+):([^:]+):([^:]+):([^:]+).*$/\1:\2:\3:\4::\/64/') || SUBNET6=$(ip -6 route show $IPV6 dev $NETWORK | awk '{print $1;exit}')
|
||||
SERVER6=${IPV6%/*}
|
||||
DHCP6=${NETWORK/./_}
|
||||
DHCP6=DOCKER_DHCP6_${DHCP6^^}
|
||||
RANGE6=${!DHCP6}
|
||||
GATEWAY6=$(ip -6 route show default dev $NETWORK | awk '{print $3;exit}')
|
||||
# replace link local address for first address in subnet
|
||||
[[ ${GATEWAY6:0:4} == fe80 ]] && GATEWAY6=${SUBNET6%/*}1
|
||||
@@ -354,8 +350,6 @@ docker_network_start(){
|
||||
GATEWAY6=DOCKER_GATEWAY6_$DEVICE
|
||||
GATEWAY6=${!GATEWAY6}
|
||||
SERVER6=;
|
||||
RANGE6=DOCKER_RANGE6_$DEVICE
|
||||
RANGE6=${!RANGE6}
|
||||
fi
|
||||
# custom network already existing and changed?
|
||||
if [[ $NETWORKS =~ "$NETWORK " ]]; then
|
||||
@@ -375,7 +369,7 @@ docker_network_start(){
|
||||
[[ -n ${SERVERS[1]} && ${SERVERS[1]} =~ '.' ]] && SERVER0=${SERVERS[1]} || SERVER1=${SERVERS[1]}
|
||||
# check for changes
|
||||
[[ $SUBNET != $SUBNET0 || $SUBNET6 != $SUBNET1 ]] && UPDATE=1
|
||||
[[ $RANGE != $RANGE0 || $RANGE6 != $RANGE1 ]] && UPDATE=1
|
||||
[[ $RANGE != $RANGE0 ]] && UPDATE=1
|
||||
[[ (-n $GATEWAY && $GATEWAY != $GATEWAY0) || (-n $GATEWAY6 && $GATEWAY6 != $GATEWAY1) ]] && UPDATE=1
|
||||
[[ (-n $SERVER && $SERVER != $SERVER0) || (-n $SERVER6 && $SERVER6 != $SERVER1) ]] && UPDATE=1
|
||||
if [[ -z $UPDATE ]]; then
|
||||
@@ -388,20 +382,19 @@ docker_network_start(){
|
||||
fi
|
||||
# set parameters for custom network creation
|
||||
N4=$SUBNET; R4=$RANGE;
|
||||
N6=$SUBNET6; R6=$RANGE6;
|
||||
N6=$SUBNET6;
|
||||
[[ -n $SUBNET && -n $GATEWAY ]] && GATEWAY="--gateway=$GATEWAY" || GATEWAY=;
|
||||
[[ -n $SUBNET && -n $SERVER ]] && SERVER="--aux-address=server=$SERVER" || SERVER=;
|
||||
[[ -n $SUBNET && -n $RANGE ]] && RANGE="--ip-range=$RANGE" || RANGE=;
|
||||
[[ -n $SUBNET ]] && SUBNET="--subnet=$SUBNET"
|
||||
[[ -n $SUBNET6 && -n $GATEWAY6 ]] && GATEWAY6="--gateway=$GATEWAY6" || GATEWAY6=;
|
||||
[[ -n $SUBNET6 && -n $SERVER6 ]] && SERVER6="--aux-address=server6=$SERVER6" || SERVER6=;
|
||||
[[ -n $SUBNET6 && -n $RANGE6 ]] && RANGE6="--ip-range=$RANGE6" || RANGE6=;
|
||||
[[ -n $SUBNET6 ]] && SUBNET6="--ipv6 --subnet=$SUBNET6"
|
||||
if [[ -n $SUBNET || -n $SUBNET6 ]]; then
|
||||
TYPE=${NETWORK//[0-9.]/}
|
||||
driver $TYPE
|
||||
[[ $TYPE == br ]] && VHOST=$NETWORK || VHOST=vhost${NETWORK//[^0-9.]/}
|
||||
docker network create -d $ATTACH $SUBNET $GATEWAY $SERVER $RANGE $SUBNET6 $GATEWAY6 $SERVER6 $RANGE6 -o parent=$VHOST $NETWORK | xargs docker network inspect -f "created network $ATTACH {{.Name}} with subnets: {{range .IPAM.Config}}{{.Subnet}}; {{end}}" 2>/dev/null | log
|
||||
docker network create -d $ATTACH $SUBNET $GATEWAY $SERVER $RANGE $SUBNET6 $GATEWAY6 $SERVER6 -o parent=$VHOST $NETWORK | xargs docker network inspect -f "created network $ATTACH {{.Name}} with subnets: {{range .IPAM.Config}}{{.Subnet}}; {{end}}" 2>/dev/null | log
|
||||
# connect containers to this new network
|
||||
for CONNECT in ${NETRESTORE[$NETWORK]}; do
|
||||
CONTAINER=${CONNECT%,*}
|
||||
@@ -425,10 +418,10 @@ docker_network_start(){
|
||||
if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then
|
||||
# create shim interface and copy parent IPv4 address to shim interface
|
||||
[[ -e $SYSTEM/$LINK ]] || run ip link add $LINK link $NETWORK type $ATTACH mode $MODE
|
||||
run ip -4 addr flush dev $LINK
|
||||
run ip addr flush dev $LINK
|
||||
run ip -4 addr add $IPV4 dev $LINK metric 0
|
||||
# disable IPv6 on shim interface
|
||||
echo 1 > $CONF6/$LINK/disable_ipv6
|
||||
echo 1 >$CONF6/$LINK/disable_ipv6
|
||||
run ip link set $LINK up
|
||||
if [[ -n $GW ]]; then
|
||||
if [[ -z ${GW[1]} ]]; then
|
||||
@@ -445,19 +438,19 @@ docker_network_start(){
|
||||
elif [[ -e $SYSTEM/$LINK ]]; then
|
||||
# remove shim interface
|
||||
[[ -n $GW ]] && ip -4 route del default via $GW dev $LINK
|
||||
run ip -4 addr flush dev $LINK
|
||||
run ip addr flush dev $LINK
|
||||
run ip link set $LINK down
|
||||
run ip link del $LINK
|
||||
fi
|
||||
else
|
||||
if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then
|
||||
run ip -4 addr flush dev $VHOST
|
||||
# copy parent IPv4 address to vhost interface
|
||||
run ip addr flush dev $VHOST
|
||||
# copy IPv4 address to vhost interface
|
||||
run ip -4 addr add $IPV4 dev $VHOST metric 0
|
||||
log "prepared network $VHOST for host access"
|
||||
elif [[ -e $SYSTEM/$VHOST ]]; then
|
||||
# remove IP addresses
|
||||
run ip -4 addr flush dev $VHOST
|
||||
run ip addr flush dev $VHOST
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -488,13 +481,13 @@ docker_network_stop(){
|
||||
if [[ -e $SYSTEM/$LINK ]]; then
|
||||
GW=$(ip -4 route show default dev $LINK | awk '{print $3;exit}')
|
||||
[[ -n $GW ]] && run ip -4 route del default via $GW dev $LINK
|
||||
run ip -4 addr flush dev $LINK
|
||||
run ip addr flush dev $LINK
|
||||
run ip link set $LINK down
|
||||
run ip link del $LINK
|
||||
fi
|
||||
else
|
||||
VHOST=vhost${NETWORK//[^0-9.]/}
|
||||
[[ -e $SYSTEM/$VHOST ]] && run ip -4 addr flush dev $VHOST
|
||||
[[ -e $SYSTEM/$VHOST ]] && run ip addr flush dev $VHOST
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
+65
-43
@@ -7,6 +7,7 @@
|
||||
# @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv)
|
||||
|
||||
# LimeTech - modified for Unraid OS
|
||||
# Bergware - modified for Unraid OS, January 2025
|
||||
|
||||
# Adapted by Bergware for use in Unraid OS - April 2016
|
||||
# - improved interface configuration
|
||||
@@ -72,7 +73,9 @@
|
||||
# Adapted by Bergware for use in Unraid OS - February 2024
|
||||
# - revised bond interface creation for linux kernel 6.6.14 and later point releases
|
||||
|
||||
# Bergware - modified for Unraid OS, February 2024
|
||||
# Adapted by Bergware for use in Unraid OS - January 2025
|
||||
# - added 'renew' command to restart interface without reconfiguring
|
||||
# - fixed dns assigment may be missing in some cases
|
||||
|
||||
###########
|
||||
# LOGGING #
|
||||
@@ -337,21 +340,23 @@ ipv6_addr(){
|
||||
|
||||
# function to assign IP address
|
||||
ipaddr_up(){
|
||||
# disable IPv6 per interface when IPv4 only
|
||||
[[ $IP == ipv4 ]] && DISABLE6=1 || DISABLE6=0
|
||||
[[ -d $CONF6/$IFACE ]] && echo $DISABLE6 >$CONF6/$IFACE/disable_ipv6
|
||||
[[ -d $CONF6/$VHOST ]] && echo $DISABLE6 >$CONF6/$VHOST/disable_ipv6
|
||||
# repeat action on related interfaces
|
||||
if [[ ${IFACE:0:4} == bond ]]; then
|
||||
ipv6_up bond br eth $DISABLE6
|
||||
elif [[ ${IFACE:0:2} == br ]]; then
|
||||
ipv6_up br bond eth $DISABLE6
|
||||
else
|
||||
ipv6_up eth bond br $DISABLE6
|
||||
if [[ -z $RENEW ]]; then
|
||||
# disable IPv6 per interface when IPv4 only
|
||||
[[ $IP == ipv4 ]] && DISABLE6=1 || DISABLE6=0
|
||||
[[ -d $CONF6/$IFACE ]] && echo $DISABLE6 >$CONF6/$IFACE/disable_ipv6
|
||||
[[ -d $CONF6/$VHOST ]] && echo $DISABLE6 >$CONF6/$VHOST/disable_ipv6
|
||||
# repeat action on related interfaces
|
||||
if [[ ${IFACE:0:4} == bond ]]; then
|
||||
ipv6_up bond br eth $DISABLE6
|
||||
elif [[ ${IFACE:0:2} == br ]]; then
|
||||
ipv6_up br bond eth $DISABLE6
|
||||
else
|
||||
ipv6_up eth bond br $DISABLE6
|
||||
fi
|
||||
fi
|
||||
if [[ $DHCP == yes ]]; then
|
||||
# bring up interface using DHCP/SLAAC
|
||||
ipv6_addr 1 1
|
||||
[[ -z $RENEW ]] && ipv6_addr 1 1
|
||||
DHCP_OPTIONS="-q -n -p -t ${DHCP_TIMEOUT[$i]:-10}"
|
||||
[[ -n $DHCP_HOSTNAME ]] && DHCP_OPTIONS="$DHCP_OPTIONS -h $DHCP_HOSTNAME"
|
||||
[[ $DHCP_KEEP_RESOLV == yes ]] && DHCP_OPTIONS="$DHCP_OPTIONS -C resolv.conf"
|
||||
@@ -436,11 +441,12 @@ ipaddr_down(){
|
||||
[[ $IP == ipv6 ]] && DHCP_OPTIONS="$DHCP_OPTIONS -6"
|
||||
# release DHCP assigned addresses
|
||||
run dhcpcd $DHCP_OPTIONS $IFACE
|
||||
sleep 1
|
||||
fi
|
||||
# release assigned addresses and routes
|
||||
[[ $IP != ipv6 ]] && ipaddr_flush 4
|
||||
[[ $IP != ipv4 ]] && ipaddr_flush 6
|
||||
if [[ -z $RENEW ]]; then
|
||||
# release assigned addresses and routes
|
||||
[[ $IP != ipv6 ]] && ipaddr_flush 4
|
||||
[[ $IP != ipv4 ]] && ipaddr_flush 6
|
||||
fi
|
||||
}
|
||||
|
||||
# function to bring up network interface
|
||||
@@ -452,18 +458,21 @@ if_up(){
|
||||
done
|
||||
# exit when interface is not found
|
||||
[[ $i -eq $MAXNICS ]] && break
|
||||
[[ -n ${BONDNICS[$i]} ]] && bond_up # create interface as bond
|
||||
[[ -n ${VLANS[$i]} ]] && vlan_up # create interface VLANs
|
||||
[[ -n ${BRNICS[$i]} ]] && br_up # create interface as bridge
|
||||
[[ -z ${BRNICS[$i]} ]] && macvtap_up # create macvtap interfaces
|
||||
# if the interface isn't in the kernel yet
|
||||
# but there's an alias for it in modules.conf
|
||||
# then it should be loaded first
|
||||
if [[ ! -e $SYSTEM/$1 ]]; then
|
||||
if modprobe -c | grep -v "^#" | grep -w "alias $1" | grep -qvw "alias $1 off"; then
|
||||
run modprobe $1
|
||||
else
|
||||
[[ $DEBUG_ETH_UP == yes ]] && log "interface $1 not present nor aliased, can't create"
|
||||
# skip interface creation when renew only
|
||||
if [[ -z $RENEW ]]; then
|
||||
[[ -n ${BONDNICS[$i]} ]] && bond_up # create interface as bond
|
||||
[[ -n ${VLANS[$i]} ]] && vlan_up # create interface VLANs
|
||||
[[ -n ${BRNICS[$i]} ]] && br_up # create interface as bridge
|
||||
[[ -z ${BRNICS[$i]} ]] && macvtap_up # create macvtap interfaces
|
||||
# if the interface isn't in the kernel yet
|
||||
# but there's an alias for it in modules.conf
|
||||
# then it should be loaded first
|
||||
if [[ ! -e $SYSTEM/$1 ]]; then
|
||||
if modprobe -c | grep -v "^#" | grep -w "alias $1" | grep -qvw "alias $1 off"; then
|
||||
run modprobe $1
|
||||
else
|
||||
[[ $DEBUG_ETH_UP == yes ]] && log "interface $1 not present nor aliased, can't create"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
# loop thru main and VLAN interfaces
|
||||
@@ -477,13 +486,15 @@ if_up(){
|
||||
fi
|
||||
# macvtap interface name
|
||||
VHOST=vhost${IFACE//[^0-9.]}
|
||||
# set main interface
|
||||
if [[ $j -eq 0 ]]; then
|
||||
# set hardware address before interface goes up
|
||||
[[ -n ${HWADDR[$i]} ]] && run ip link set $1 addr ${HWADDR[$i]}
|
||||
set_mtu $1
|
||||
if [[ -z $RENEW ]]; then
|
||||
# set main interface
|
||||
if [[ $j -eq 0 ]]; then
|
||||
# set hardware address before interface goes up
|
||||
[[ -n ${HWADDR[$i]} ]] && run ip link set $1 addr ${HWADDR[$i]}
|
||||
set_mtu $1
|
||||
fi
|
||||
run ip link set $IFACE up
|
||||
fi
|
||||
run ip link set $IFACE up
|
||||
# set interface address
|
||||
[[ $i -eq 0 && $j -eq 0 ]] && MAIN=1 || MAIN=
|
||||
if [[ $IP == ipv4 ]]; then
|
||||
@@ -545,23 +556,27 @@ if_down(){
|
||||
else
|
||||
[[ $j -eq 0 ]] && DHCP=${USE_DHCP[$i]} || DHCP=${USE_DHCP[$i,$j]}
|
||||
[[ $j -eq 0 ]] && DHCP6=${USE_DHCP6[$i]} || DHCP6=${USE_DHCP6[$i,$j]}
|
||||
[[ $j -eq 0 ]] && DHCP_KEEP_RESOLV=$DHCP_KEEPRESOLV || DHCP_KEEP_RESOLV=yes
|
||||
[[ -n $MAIN ]] && DHCP_KEEP_RESOLV=$DHCP_KEEPRESOLV || DHCP_KEEP_RESOLV=yes
|
||||
[[ -n $MAIN ]] && DHCP6_KEEP_RESOLV=$DHCP6_KEEPRESOLV || DHCP6_KEEP_RESOLV=yes
|
||||
IP=ipv4
|
||||
ipaddr_down
|
||||
IP=ipv6
|
||||
DHCP=$DHCP6
|
||||
[[ $j -eq 0 ]] && DHCP_KEEP_RESOLV=$DHCP6_KEEPRESOLV || DHCP_KEEP_RESOLV=yes
|
||||
DHCP_KEEP_RESOLV=$DHCP6_KEEP_RESOLV
|
||||
ipaddr_down
|
||||
fi
|
||||
run ip link set $IFACE down
|
||||
[[ -z $RENEW ]] && run ip link set $IFACE down
|
||||
else
|
||||
[[ $DEBUG_ETH_UP == yes ]] && log "interface $IFACE not present, can't take down"
|
||||
fi
|
||||
done
|
||||
[[ -z ${BRNICS[$i]} ]] && macvtap_down # delete macvtap interfaces
|
||||
[[ -n ${BRNICS[$i]} ]] && br_down # delete interface as bridge
|
||||
[[ -n ${VLANS[$i]} ]] && vlan_down # delete interface VLANs
|
||||
[[ -n ${BONDNICS[$i]} ]] && bond_down # delete interface as bond
|
||||
# skip interface deletion when renew only
|
||||
if [[ -z $RENEW ]]; then
|
||||
[[ -z ${BRNICS[$i]} ]] && macvtap_down # delete macvtap interfaces
|
||||
[[ -n ${BRNICS[$i]} ]] && br_down # delete interface as bridge
|
||||
[[ -n ${VLANS[$i]} ]] && vlan_down # delete interface VLANs
|
||||
[[ -n ${BONDNICS[$i]} ]] && bond_down # delete interface as bond
|
||||
fi
|
||||
}
|
||||
|
||||
#####################
|
||||
@@ -717,6 +732,13 @@ restart)
|
||||
if_up $INTERFACE
|
||||
gateway_up
|
||||
;;
|
||||
*_renew)
|
||||
RENEW=1
|
||||
INTERFACE=$(echo $1 | cut -d_ -f1)
|
||||
CMD=$(echo $1 | cut -d_ -f2)
|
||||
[[ $CMD == start ]] && if_up $INTERFACE
|
||||
[[ $CMD == stop ]] && if_down $INTERFACE
|
||||
;;
|
||||
*_add)
|
||||
INTERFACE=$(echo $1 | cut -d_ -f1)
|
||||
ROUTE=$(echo $1 | cut -d_ -f2)
|
||||
@@ -731,11 +753,11 @@ restart)
|
||||
[[ $METRIC == del ]] && METRIC=
|
||||
route_down $INTERFACE $ROUTE $METRIC
|
||||
;;
|
||||
# default is to bring up the entire network
|
||||
status)
|
||||
status $2
|
||||
;;
|
||||
*)
|
||||
# default is to bring up the entire network
|
||||
start
|
||||
esac
|
||||
exit 0
|
||||
|
||||
@@ -78,18 +78,18 @@ echo -n >$RESOLV.tail
|
||||
|
||||
if [[ $DHCP_KEEPRESOLV == yes ]]; then
|
||||
echo "# Generated by rc.inet1" >>$RESOLV
|
||||
[[ -n $DNS_SERVER1 ]] && echo "nameserver $(unzero $DNS_SERVER1)" >>$RESOLV
|
||||
[[ -n $DNS_SERVER2 ]] && echo "nameserver $(unzero $DNS_SERVER2)" >>$RESOLV
|
||||
[[ -n $DNS_SERVER3 ]] && echo "nameserver $(unzero $DNS_SERVER3)" >>$RESOLV
|
||||
[[ -n $DNS_SERVER4 ]] && echo "nameserver $(unzero $DNS_SERVER4)" >>$RESOLV
|
||||
[[ -n $DNS_SERVER1 ]] && echo "nameserver $(unzero $DNS_SERVER1) # eth0:v4" >>$RESOLV
|
||||
[[ -n $DNS_SERVER2 ]] && echo "nameserver $(unzero $DNS_SERVER2) # eth0:v4" >>$RESOLV
|
||||
[[ -n $DNS_SERVER3 ]] && echo "nameserver $(unzero $DNS_SERVER3) # eth0:v4" >>$RESOLV
|
||||
[[ -n $DNS_SERVER4 ]] && echo "nameserver $(unzero $DNS_SERVER4) # eth0:v4" >>$RESOLV
|
||||
[[ $DHCP6_KEEPRESOLV == no ]] && cp -f $RESOLV $RESOLV.head
|
||||
fi
|
||||
if [[ $DHCP6_KEEPRESOLV == yes ]]; then
|
||||
[[ $DHCP_KEEPRESOLV == no ]] && echo "# Generated by rc.inet1" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER1 ]] && echo "nameserver $(unzero6 $DNS6_SERVER1)" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER2 ]] && echo "nameserver $(unzero6 $DNS6_SERVER2)" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER3 ]] && echo "nameserver $(unzero6 $DNS6_SERVER3)" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER4 ]] && echo "nameserver $(unzero6 $DNS6_SERVER4)" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER1 ]] && echo "nameserver $(unzero6 $DNS6_SERVER1) # eth0:v6" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER2 ]] && echo "nameserver $(unzero6 $DNS6_SERVER2) # eth0:v6" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER3 ]] && echo "nameserver $(unzero6 $DNS6_SERVER3) # eth0:v6" >>$RESOLV
|
||||
[[ -n $DNS6_SERVER4 ]] && echo "nameserver $(unzero6 $DNS6_SERVER4) # eth0:v6" >>$RESOLV
|
||||
[[ $DHCP_KEEPRESOLV == no ]] && cp -f $RESOLV $RESOLV.tail
|
||||
fi
|
||||
|
||||
|
||||
@@ -5,11 +5,20 @@
|
||||
# Library used by nfsd, ntpd, rpc, samba, nginx, sshd, avahidaemon, show_interfaces
|
||||
#
|
||||
# Bergware - created for Unraid OS, December 2023
|
||||
# Bergware - updated January 2025
|
||||
|
||||
WIREGUARD="/etc/wireguard"
|
||||
NETWORK_INI="/var/local/emhttp/network.ini"
|
||||
NETWORK_EXTRA="/boot/config/network-extra.cfg"
|
||||
|
||||
var(){
|
||||
if [[ $# -eq 3 ]]; then
|
||||
[[ -r "$3" ]] && sed -n "/^\[$1\]\$/,/^\[/p" "$3" | grep -Pom1 "^$2=\"\K[^\"]+"
|
||||
elif [[ $# -eq 2 ]]; then
|
||||
[[ -r "$2" ]] && grep -Pom1 "^$1=\"\K[^\"]+" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
ipv(){
|
||||
local t=${1//[^:]}
|
||||
[[ ${#t} -le 1 ]] && echo 4 || echo 6
|
||||
@@ -47,8 +56,8 @@ good(){
|
||||
|
||||
show(){
|
||||
case $# in
|
||||
1) ip -br addr show scope global to $1 2>/dev/null | awk '{gsub("@.+","",$1);print $1;exit}' ;;
|
||||
2) ip -br addr show scope global $1 $2 2>/dev/null | awk '{$1=$2="";print;exit}' | sed -r 's/ metric [0-9]+//g' ;;
|
||||
1) ip -br addr show scope global -temporary -deprecated to $1 2>/dev/null | awk '{gsub("@.+","",$1);print $1;exit}' ;;
|
||||
2) ip -br addr show scope global -temporary -deprecated $1 $2 2>/dev/null | awk '{$1=$2="";print;exit}' | sed -r 's/ metric [0-9]+//g' ;;
|
||||
esac
|
||||
}
|
||||
|
||||
@@ -151,7 +160,7 @@ check(){
|
||||
fi
|
||||
[[ $(ipv $ADDR) == 4 ]] && IPV4=yes || IPV6=yes
|
||||
done
|
||||
done <<< $(ip -br addr show scope global | awk '$1~"^(br|bond|eth|wg)[0-9]+(.[0-9]+)?" && $3!="" {gsub("@.+","",$1);$2="";print}' | sed -r 's/ metric [0-9]+//g' | sort)
|
||||
done <<< $(ip -br addr show scope global -temporary -deprecated | awk '$1~"^(br|bond|eth|wlan|wg)[0-9]+(.[0-9]+)?" && $3!="" {gsub("@.+","",$1);$2="";print}' | sed -r 's/ metric [0-9]+//g' | sort)
|
||||
# add loopback interface
|
||||
if [[ "smb nfs" =~ "$CALLER" ]]; then
|
||||
[[ $IPV4 == yes ]] && BIND+=(127.0.0.1)
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ vmlist(){
|
||||
waitfor(){
|
||||
local C=0
|
||||
while [[ $C -lt $TIMEOUT && $(virsh list --state-$1 | awk "NR>2 && /${2:-^.+$}/" | wc -l) -gt 0 ]]; do
|
||||
if [ $C -eq 0 ]; then # echo Timeout info just one time and only if virsh returned something
|
||||
if [[ $C -eq 0 ]]; then # echo Timeout info just one time and only if virsh returned something
|
||||
log "Waiting $TIMEOUT seconds for VMs with state: $1"
|
||||
fi
|
||||
((C++))
|
||||
|
||||
+8
-10
@@ -15,21 +15,19 @@
|
||||
. /etc/rc.d/rc.runlog
|
||||
|
||||
# import CA proxy
|
||||
UnProxy=/boot/config/plugins/dynamix/outgoingproxy.cfg
|
||||
CAProxy=/boot/config/plugins/community.applications/proxy.cfg
|
||||
if [[ -f "${CAProxy}" && ! -f "${UnProxy}" ]]; then
|
||||
proxy=
|
||||
port=
|
||||
. "${CAProxy}"
|
||||
UNPROXY=/boot/config/plugins/dynamix/outgoingproxy.cfg
|
||||
CAPROXY=/boot/config/plugins/community.applications/proxy.cfg
|
||||
if [[ -f $CAPROXY && ! -f $UNPROXY ]]; then
|
||||
. $CAPROXY
|
||||
# proxy and port were set by the previous command
|
||||
if [[ -n "${proxy}" && -n "${port}" ]]; then
|
||||
cat << EOF > "${UnProxy}"
|
||||
if [[ -n $proxy && -n $port ]]; then
|
||||
cat << EOF > $UNPROXY
|
||||
proxy_active="1"
|
||||
proxy_url_1="${proxy}:${port}"
|
||||
proxy_url_1="$proxy:$port"
|
||||
proxy_name_1="Imported from CA"
|
||||
EOF
|
||||
fi
|
||||
mv "${CAProxy}" "${CAProxy}~"
|
||||
mv "$CAPROXY" "$CAPROXY~"
|
||||
fi
|
||||
|
||||
# load proxy environment vars so it is used for plugin updates and the go script
|
||||
|
||||
+5
-5
@@ -16,19 +16,19 @@ if [[ -f /boot/unraidsafemode ]] || grep -wq unraidsafemode /proc/cmdline; then
|
||||
log "Unraid Safe Mode (unraidsafemode) has been set, skip driver installation"
|
||||
else
|
||||
log "Installing third-party drivers..."
|
||||
find /boot/config/plugins/*/packages/${RELEASE%%-*}/ -maxdepth 1 -type f 2>/dev/null | while read -r PKG; do
|
||||
/usr/bin/find /boot/config/plugins/*/packages/${RELEASE%%-*}/ -maxdepth 1 -type f 2>/dev/null | while read -r PKG; do
|
||||
if [[ $PKG == *"-$RELEASE-"*.t?z ]]; then
|
||||
if [[ -f $PKG.md5 ]]; then
|
||||
HASH1=$(md5sum $PKG)
|
||||
HASH2=$(cat $PKG.md5)
|
||||
HASH1=$(/bin/md5sum $PKG)
|
||||
HASH2=$(/bin/cat $PKG.md5)
|
||||
if [[ ${HASH1:0:32} != ${HASH2:0:32} ]]; then
|
||||
log "Package $PKG has MD5 error, not installing"
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
if [[ -f $PKG.sha256 ]]; then
|
||||
HASH1=$(sha256sum $PKG)
|
||||
HASH2=$(cat $PKG.sha256)
|
||||
HASH1=$(/bin/sha256sum $PKG)
|
||||
HASH2=$(/bin/cat $PKG.sha256)
|
||||
if [[ ${HASH1:0:64} != ${HASH2:0:64} ]]; then
|
||||
log "Package $PKG has SHA256 error, not installing"
|
||||
continue
|
||||
|
||||
+22
-21
@@ -5,15 +5,15 @@
|
||||
# Start/stop/restart ntpd.
|
||||
#
|
||||
# LimeTech - modified to initialize ntp.conf file from config
|
||||
# Bergware - modified for Unraid OS, October 2023
|
||||
# Bergware - modified for Unraid OS, December 2024
|
||||
|
||||
DAEMON="NTP server daemon"
|
||||
CALLER="ntp"
|
||||
NTPD="/usr/sbin/ntpd"
|
||||
OPTIONS="-g -u ntp:ntp"
|
||||
CONF="/etc/ntp.conf"
|
||||
CFG="/boot/config/plugins/dynamix/dynamix.cfg"
|
||||
IDENT="/boot/config/ident.cfg"
|
||||
CONFIG="/boot/config/plugins/dynamix/dynamix.cfg"
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
@@ -39,24 +39,25 @@ ntpd_build(){
|
||||
echo "interface listen $NET" >>$CONF
|
||||
done
|
||||
fi
|
||||
NTP_POLL=$(var NTP POLL $CFG)
|
||||
# ntp poll interval may be adjusted to predefined values
|
||||
if [[ -f $CONFIG ]]; then
|
||||
NTP_POLL=$(grep -Po '^ntppoll="\K[^"]+' $CONFIG)
|
||||
if [[ -n $NTP_POLL ]]; then
|
||||
MINPOLL="minpoll $NTP_POLL"
|
||||
MAXPOLL="maxpoll $NTP_POLL"
|
||||
fi
|
||||
if [[ -n $NTP_POLL ]]; then
|
||||
MINPOLL="minpoll $NTP_POLL"
|
||||
MAXPOLL="maxpoll $NTP_POLL"
|
||||
fi
|
||||
# allow ntp to use ptp as sync source
|
||||
if [[ $(var PTP SYNC $CFG) != yes ]]; then
|
||||
# add configured ntp servers or pools
|
||||
for n in {1..4}; do
|
||||
NTP="NTP_SERVER$n"
|
||||
if [[ -n ${!NTP} ]]; then
|
||||
# use either server or pool peers depending on remote ntp name
|
||||
# pools use a round-robin mechanism to get a server out of the pool
|
||||
[[ ${!NTP} =~ "pool" ]] && PEER=pool || PEER=server
|
||||
echo "$PEER ${!NTP} iburst $MINPOLL $MAXPOLL" >>$CONF
|
||||
fi
|
||||
done
|
||||
fi
|
||||
# add configured ntp servers or pools
|
||||
for n in {1..4}; do
|
||||
NTP="NTP_SERVER$n"
|
||||
if [[ -n ${!NTP} ]]; then
|
||||
# use either server or pool peers depending on remote ntp name
|
||||
# pools use a round-robin mechanism to get a server out of the pool
|
||||
[[ ${!NTP} =~ "pool" ]] && PEER=pool || PEER=server
|
||||
echo "$PEER ${!NTP} iburst $MINPOLL $MAXPOLL" >>$CONF
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
ntpd_start(){
|
||||
@@ -64,7 +65,7 @@ ntpd_start(){
|
||||
local REPLY
|
||||
# read Unraid settings
|
||||
[[ -r $IDENT ]] && . <(fromdos <$IDENT)
|
||||
# if ntp not enabled, don't start ntp
|
||||
# if time sync not enabled, don't start ntp
|
||||
if [[ $USE_NTP != yes ]]; then
|
||||
REPLY="Service not enabled"
|
||||
elif ntpd_running; then
|
||||
@@ -90,7 +91,7 @@ ntpd_stop(){
|
||||
kill -HUP $(cat /var/run/ntpd.pid)
|
||||
rm -f /var/run/ntpd.pid
|
||||
else
|
||||
killall --ns $$ -HUP -q ntpd
|
||||
killall --ns $$ -HUP -q ntpd
|
||||
fi
|
||||
if ! ntpd_running; then REPLY="Stopped"; else REPLY="Failed"; fi
|
||||
fi
|
||||
@@ -107,7 +108,7 @@ ntpd_restart(){
|
||||
}
|
||||
|
||||
ntpd_reload(){
|
||||
killall --ns $$ -HUP -q ntpd
|
||||
killall --ns $$ -HUP -q ntpd
|
||||
. <(fromdos <$IDENT)
|
||||
ntpd_build
|
||||
$NTPD $OPTIONS 2>/dev/null
|
||||
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# script: rc.ptpd
|
||||
#
|
||||
# Start/stop/restart services ptp4l and phc2sys.
|
||||
#
|
||||
# Bergware - created for Unraid OS, December 2024
|
||||
|
||||
DAEMON="PTP server daemon"
|
||||
CALLER="ptp"
|
||||
PTPD="/usr/sbin/ptp4l"
|
||||
PHC="/usr/sbin/phc2sys"
|
||||
OPTIONS1="-s -l 5 -f /etc/ptp4l.conf"
|
||||
OPTIONS2="-a -r -l 5"
|
||||
CONF="/etc/ptp4l.conf"
|
||||
CFG="/boot/config/plugins/dynamix/dynamix.cfg"
|
||||
IDENT="/boot/config/ident.cfg"
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
|
||||
# library functions
|
||||
. /etc/rc.d/rc.library.source
|
||||
|
||||
ptpd_running(){
|
||||
sleep 0.1
|
||||
[[ $(pgrep -cf $PTPD) -gt 0 ]]
|
||||
}
|
||||
|
||||
ptpd_build(){
|
||||
echo "[global]" >$CONF
|
||||
TRANSPORT=$(var PTP TRANSPORT $CFG)
|
||||
echo "network_transport $TRANSPORT" >>$CONF
|
||||
echo "time_stamping $(var PTP CLOCK $CFG)" >>$CONF
|
||||
[[ $(var PTP MODE $CFG) == unicast ]] && UNICAST=1 || UNICAST=0
|
||||
if [[ $UNICAST == 1 ]]; then
|
||||
echo "unicast_req_duration 60" >>$CONF
|
||||
echo "" >>$CONF
|
||||
echo "[unicast_master_table]" >>$CONF
|
||||
echo "table_id 1" >>$CONF
|
||||
echo "logQueryInterval 1" >>$CONF
|
||||
for n in {1..4}; do
|
||||
PTP=$(var PTP "SERVER$n" $CFG)
|
||||
[[ -n $PTP ]] && echo "$TRANSPORT $PTP" >>$CONF
|
||||
done
|
||||
fi
|
||||
echo "" >>$CONF
|
||||
echo "[$(var PTP PORT $CFG)]" >>$CONF
|
||||
[[ $UNICAST == 1 ]] && echo "unicast_master_table 1" >>$CONF
|
||||
}
|
||||
|
||||
ptpd_start(){
|
||||
log "Starting $DAEMON..."
|
||||
local REPLY
|
||||
# read Unraid settings
|
||||
[[ -r $IDENT ]] && . <(fromdos <$IDENT)
|
||||
# if time sync not enabled, don't start ptp
|
||||
if [[ $USE_NTP != yes ]]; then
|
||||
REPLY="Service not enabled"
|
||||
elif [[ $(var PTP SYNC $CFG) == yes || $FORCE == yes ]]; then
|
||||
if ptpd_running; then
|
||||
REPLY="Already started"
|
||||
else
|
||||
# generate our config file
|
||||
ptpd_build
|
||||
$PTPD $OPTIONS1 &>/dev/null &
|
||||
if ptpd_running; then
|
||||
$PHC $OPTIONS2 &>/dev/null &
|
||||
REPLY="Started"
|
||||
else
|
||||
REPLY="Failed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
REPLY="Not started"
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
ptpd_stop(){
|
||||
log "Stopping $DAEMON..."
|
||||
local REPLY
|
||||
if ! ptpd_running; then
|
||||
REPLY="Already stopped"
|
||||
else
|
||||
pkill -f $PTPD 2>/dev/null
|
||||
pkill -f $PHC 2>/dev/null
|
||||
if ! ptpd_running; then REPLY="Stopped"; else REPLY="Failed"; fi
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
ptpd_restart(){
|
||||
log "Restarting $DAEMON..."
|
||||
ptpd_stop
|
||||
sleep 1
|
||||
ptpd_start
|
||||
}
|
||||
|
||||
ptpd_status(){
|
||||
if ptpd_running; then
|
||||
echo "$DAEMON is currently running."
|
||||
else
|
||||
echo "$DAEMON is not running."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
ptpd_start
|
||||
;;
|
||||
'forcestart')
|
||||
FORCE=yes
|
||||
ptpd_start
|
||||
;;
|
||||
'stop')
|
||||
ptpd_stop
|
||||
;;
|
||||
'restart')
|
||||
ptpd_restart
|
||||
;;
|
||||
'status')
|
||||
ptpd_status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $BASENAME start|forcestart|stop|restart|status"
|
||||
exit 1
|
||||
esac
|
||||
exit 0
|
||||
@@ -38,6 +38,7 @@ samba_running(){
|
||||
}
|
||||
|
||||
samba_waitfor_shutdown(){
|
||||
local i
|
||||
for i in {1..5}; do
|
||||
if ! samba_running; then break; fi
|
||||
sleep 1
|
||||
|
||||
+4
-4
@@ -66,16 +66,16 @@ done
|
||||
# Handle System V init conventions...
|
||||
case "$1" in
|
||||
'start')
|
||||
action="start"
|
||||
ACTION="start"
|
||||
;;
|
||||
'stop')
|
||||
action="stop"
|
||||
ACTION="stop"
|
||||
;;
|
||||
*)
|
||||
action="start"
|
||||
ACTION="start"
|
||||
esac
|
||||
|
||||
if [[ $action == stop ]]; then
|
||||
if [[ $ACTION == stop ]]; then
|
||||
if [[ -n $SETSERIAL && $LOADED != no && "$(head -1 $SERIAL)X" == "###AUTOSAVE###X" ]]; then
|
||||
log "Saving state of serial devices."
|
||||
grep "^#" $SERIAL >/etc/.serial.conf.new
|
||||
|
||||
Executable
+304
@@ -0,0 +1,304 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# script: rc.wireless
|
||||
#
|
||||
# This script is used to bring up the wireless network interface.
|
||||
#
|
||||
# Bergware - created for Unraid OS, January 2025
|
||||
|
||||
DAEMON="WiFi network"
|
||||
CALLER="wifi"
|
||||
INI="/var/local/emhttp/wireless.ini"
|
||||
CFG="/boot/config/wireless.cfg"
|
||||
SSLINPUT="/etc/rc.d/rc.ssl.input"
|
||||
STARTWIFI="/usr/local/emhttp/webGui/scripts/wireless"
|
||||
WPA="/etc/wpa_supplicant.conf"
|
||||
|
||||
# system network references
|
||||
SYSTEM=/sys/class/net
|
||||
CONF6=/proc/sys/net/ipv6/conf
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
|
||||
# library functions
|
||||
. /etc/rc.d/rc.library.source
|
||||
|
||||
# get settings
|
||||
[[ -r $INI ]] && . $INI
|
||||
PORT=${PORT:-wlan0}
|
||||
|
||||
# function to remove leading zeros in IPv4 address
|
||||
unzero(){
|
||||
local M Q
|
||||
echo -n $(for Q in ${1//./ }; do printf "$M%x" "0x$Q"; M=.; done)
|
||||
}
|
||||
|
||||
# function to remove leading zeros in IPv6 address
|
||||
unzero6(){
|
||||
local A M Q
|
||||
A=${1/::/:-:}
|
||||
echo -n $(for Q in ${A//:/ }; do [[ $Q != - ]] && printf "$M%x" "0x$Q" || printf ":"; M=:; done)
|
||||
}
|
||||
|
||||
# function to initialize openSSL variables
|
||||
ssl_init(){
|
||||
KEY="$(dmidecode -qt1 | grep -Pom1 'Manufacturer: \K.+' | sed 's/ /_/g')ABCDEFGH"
|
||||
IV="$(dmidecode -qt1 | grep -Pom1 'Product Name: \K.+' | sed 's/ /_/g')1234567890123456"
|
||||
echo "cipher=aes-256-cbc" >$SSLINPUT
|
||||
echo "key=${KEY:0:63}" >>$SSLINPUT
|
||||
echo "iv=${IV:0:16}" >>$SSLINPUT
|
||||
}
|
||||
|
||||
# function to convert text to hex
|
||||
hex(){
|
||||
echo -n $1 | od -An -tx1 | tr -d ' \n'
|
||||
}
|
||||
|
||||
# function to wait for carrier of interface
|
||||
carrier_up(){
|
||||
local n
|
||||
for n in {1..10}; do
|
||||
[[ $(cat $SYSTEM/$1/carrier 2>/dev/null) == 1 ]] && return 0 || sleep 1
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# function to enable/disable ipv6 assignment per interface
|
||||
ipv6_addr(){
|
||||
if [[ -d $CONF6/$1 ]]; then
|
||||
echo $2 >$CONF6/$1/accept_ra
|
||||
echo $2 >$CONF6/$1/accept_ra_defrtr
|
||||
echo $3 >$CONF6/$1/autoconf
|
||||
fi
|
||||
}
|
||||
|
||||
# function to assign IP address
|
||||
ipaddr_up(){
|
||||
# disable IPv6 per interface when IPv4 only
|
||||
[[ $IP == ipv4 ]] && DISABLE6=1 || DISABLE6=0
|
||||
[[ -d $CONF6/$PORT ]] && echo $DISABLE6 >$CONF6/$PORT/disable_ipv6
|
||||
if [[ $DHCP == yes ]]; then
|
||||
# bring up interface using DHCP/SLAAC
|
||||
ipv6_addr 1 1
|
||||
OPTIONS="-q -n -p -t 10"
|
||||
[[ -n $HOSTNAME ]] && OPTIONS="$OPTIONS -h $HOSTNAME"
|
||||
[[ $DNS == yes ]] && OPTIONS="$OPTIONS -C resolv.conf"
|
||||
[[ $IP == ipv4 ]] && OPTIONS="$OPTIONS -4"
|
||||
[[ $IP == ipv6 ]] && OPTIONS="$OPTIONS -6"
|
||||
if carrier_up $PORT; then
|
||||
# interface is UP
|
||||
log "interface $PORT is UP, polling up to 60 sec for DHCP $IP server"
|
||||
if ! run timeout 60 dhcpcd -w $OPTIONS $PORT; then
|
||||
log "can't obtain IP address, continue polling in background on interface $PORT"
|
||||
run dhcpcd -b $OPTIONS $PORT
|
||||
fi
|
||||
else
|
||||
# interface is DOWN
|
||||
log "interface $PORT is DOWN, polling DHCP $IP server in background"
|
||||
run dhcpcd -b $OPTIONS $PORT
|
||||
fi
|
||||
elif [[ $DHCP == no ]]; then
|
||||
# bring up interface using static IP address
|
||||
if carrier_up $PORT; then STATE="UP"; else STATE="DOWN"; fi
|
||||
log "interface $PORT is $STATE, setting static $IP address"
|
||||
ipv6_addr $PORT 0 1
|
||||
if [[ $IP == ipv4 ]]; then
|
||||
[[ -n $IP4 && -n $MASK4 ]] && run ip -4 addr add $(unzero $IP4)/$MASK4 dev $PORT metric 3004
|
||||
[[ -n $GATEWAY4 ]] && run ip -4 route add default via $GATEWAY4 dev $PORT metric 3004
|
||||
fi
|
||||
if [[ $IP == ipv6 ]]; then
|
||||
[[ -n $IP6 && -n $MASK6 ]] && run ip -6 addr add $(unzero6 $IP6)/$MASK6 dev $PORT metric 3004
|
||||
[[ -n $GATEWAY6 ]] && run ip -6 route add default via $GATEWAY6 dev $PORT metric 3004
|
||||
fi
|
||||
fi
|
||||
if [[ $DNS == yes ]]; then
|
||||
[[ $IP == ipv4 ]] && echo "nameserver $SERVER4 # $PORT:v4" >>/etc/resolv.conf
|
||||
[[ $IP == ipv6 ]] && echo "nameserver $SERVER6 # $PORT:v6" >>/etc/resolv.conf
|
||||
else
|
||||
[[ $IP == ipv4 ]] && sed -ri '/^nameserver .+# $PORT:v4/d' /etc/resolv.conf
|
||||
[[ $IP == ipv6 ]] && sed -ri '/^nameserver .+# $PORT:v6/d' /etc/resolv.conf
|
||||
fi
|
||||
}
|
||||
|
||||
# function to release IP address
|
||||
ipaddr_down(){
|
||||
if [[ $DHCP == yes ]]; then
|
||||
# release DHCP assigned address and default route
|
||||
OPTIONS="-q -k"
|
||||
[[ $DNS == yes ]] && OPTIONS="$OPTIONS -C resolv.conf"
|
||||
[[ $IP == ipv4 ]] && OPTIONS="$OPTIONS -4"
|
||||
[[ $IP == ipv6 ]] && OPTIONS="$OPTIONS -6"
|
||||
run dhcpcd $OPTIONS $PORT
|
||||
elif [[ $DHCP == no ]]; then
|
||||
# release static assigned address and default route
|
||||
[[ $IP == ipv4 ]] && run ip -4 addr flush dev $PORT
|
||||
[[ $IP == ipv4 ]] && run ip -4 route flush default dev $PORT
|
||||
[[ $IP == ipv6 ]] && run ip -6 addr flush dev $PORT
|
||||
[[ $IP == ipv6 ]] && run ip -6 route flush default dev $PORT
|
||||
fi
|
||||
}
|
||||
|
||||
# Security protocols Test Result
|
||||
# Open OK
|
||||
# WEP (deprecated) --
|
||||
# WPA2 OK
|
||||
# WPA2/WPA3 OK
|
||||
# WPA3 OK
|
||||
# WPA2 Enterprise OK
|
||||
# WPA2/WPA3 Enterprise OK
|
||||
# WPA3 Enterprise dynamic IP NOK, static IP OK
|
||||
|
||||
wpa_configuration(){
|
||||
PSK=$(wpa_passphrase "$SSID" "$PASSWORD" 2>/dev/null | grep -Pom1 '^\s+psk=\K.+')
|
||||
[[ -z $PSK ]] && PSK="\"$PASSWORD\""
|
||||
echo "bgscan=\"\"" >$WPA
|
||||
echo "network={" >>$WPA
|
||||
echo "ssid=\"$SSID\"" >>$WPA
|
||||
[[ $1 == "PSK" ]] && echo "key_mgmt=WPA-PSK" >>$WPA
|
||||
[[ $1 == "SAE" ]] && echo "key_mgmt=SAE" >>$WPA
|
||||
[[ $1 =~ "IEEE" && $1 != "IEEE 802.1X/SHA-256" ]] && echo "key_mgmt=WPA-EAP" >>$WPA
|
||||
[[ $1 == "IEEE 802.1X/SHA-256" ]] && echo "key_mgmt=WPA-EAP-SHA256" >>$WPA
|
||||
[[ $1 =~ "IEEE 802.1X" ]] && echo "eap=PEAP" >>$WPA
|
||||
[[ $1 != "SAE" && ! $1 =~ "IEEE" ]] && echo "psk=$PSK" >>$WPA
|
||||
[[ $1 =~ "IEEE" ]] && echo "identity=\"$USERNAME\"" >>$WPA
|
||||
[[ $1 =~ "IEEE" && $1 != "IEEE 802.1X/SHA-256" ]] && echo "password=\"$PASSWORD\"" >>$WPA
|
||||
[[ $1 == "SAE" || $1 == "IEEE 802.1X/SHA-256" ]] && echo "sae_password=\"$PASSWORD\"" >>$WPA
|
||||
[[ $1 == "SAE" || $1 == "IEEE 802.1X/SHA-256" ]] && echo "ieee80211w=2" >>$WPA
|
||||
[[ $1 =~ "IEEE" ]] && echo "phase1=\"peaplabel=0\"" >>$WPA
|
||||
[[ $1 =~ "IEEE" ]] && echo "phase2=\"auth=MSCHAPV2\"" >>$WPA
|
||||
echo "}" >>$WPA
|
||||
}
|
||||
|
||||
wifi_running(){
|
||||
sleep 0.1
|
||||
[[ $(cat $SYSTEM/$PORT/carrier 2>/dev/null) == 1 ]]
|
||||
}
|
||||
|
||||
wifi_start(){
|
||||
log "Starting $DAEMON..."
|
||||
local REPLY
|
||||
if [[ -e $SYSTEM/$PORT ]]; then
|
||||
run ip link set $PORT up
|
||||
ssl_init
|
||||
# start active SSID
|
||||
$STARTWIFI
|
||||
if ! carrier_up $PORT; then
|
||||
# try the saved SSIDs
|
||||
for SSID in $(grep -P '^\[.+\]$' $CFG 2>/dev/null | sed 1d | sed -r 's/\[|\]/"/g'); do
|
||||
[[ -n $SSID ]] && $STARTWIFI "$SSID" || break
|
||||
if carrier_up $PORT; then break; fi
|
||||
done
|
||||
fi
|
||||
if wifi_running; then REPLY="Started"; else REPLY="Failed"; fi
|
||||
else
|
||||
REPLY="No Wifi present"
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
wifi_stop(){
|
||||
log "Stopping $DAEMON..."
|
||||
local REPLY
|
||||
if [[ -e $SYSTEM/$PORT ]]; then
|
||||
IP=ipv4
|
||||
DHCP=$DHCP4
|
||||
DNS=$DNS4
|
||||
ipaddr_down
|
||||
if [[ -n $DHCP6 ]]; then
|
||||
IP=ipv6
|
||||
DHCP=$DHCP6
|
||||
DNS=$DNS6
|
||||
ipaddr_down
|
||||
fi
|
||||
pkill wpa_supplicant
|
||||
iw dev $PORT disconnect 2>/dev/null
|
||||
rm -f $INI
|
||||
if ! wifi_running; then REPLY="Stopped"; else REPLY="Failed"; fi
|
||||
else
|
||||
REPLY="No Wifi present"
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
wifi_join(){
|
||||
log "Joining $DAEMON..."
|
||||
local REPLY
|
||||
if [[ ! -r $CFG ]]; then
|
||||
log "$DAEMON... No configuration."
|
||||
return
|
||||
fi
|
||||
[[ -e $SSLINPUT ]] || ssl_init
|
||||
# get SSL keys
|
||||
. $SSLINPUT
|
||||
[[ -n $USERNAME ]] && USERNAME=$(echo $USERNAME | openssl $cipher -a -d -K $(hex $key) -iv $(hex $iv) 2>/dev/null)
|
||||
[[ -n $PASSWORD ]] && PASSWORD=$(echo $PASSWORD | openssl $cipher -a -d -K $(hex $key) -iv $(hex $iv) 2>/dev/null)
|
||||
SECURITY=${SECURITY:-$ATTR3}
|
||||
if [[ -z $SECURITY || ${SECURITY^^} == "OPEN" ]]; then
|
||||
# open network
|
||||
iw dev $PORT connect "$SSID" auth open 2>/dev/null
|
||||
elif [[ $SECURITY =~ "WEP" ]]; then
|
||||
# WEP encryption
|
||||
iw dev $PORT connect "$SSID" auth shared key 0:$(hex "$PASSWORD") 2>/dev/null
|
||||
else
|
||||
# WPA encryption
|
||||
wpa_configuration "$SECURITY"
|
||||
[[ -n $(pgrep wpa_supplicant) ]] && pkill wpa_supplicant
|
||||
wpa_supplicant -B -i $PORT -c $WPA 2>/dev/null
|
||||
fi
|
||||
# IPv4 address assignment
|
||||
IP=ipv4
|
||||
DHCP=$DHCP4
|
||||
DNS=$DNS4
|
||||
ipaddr_up
|
||||
# IPv6 address assignment (if enabled)
|
||||
if [[ -n $DHCP6 ]]; then
|
||||
echo 0 >$CONF6/$PORT/disable_ipv6
|
||||
IP=ipv6
|
||||
DHCP=$DHCP6
|
||||
DNS=$DNS6
|
||||
ipaddr_up
|
||||
else
|
||||
echo 1 >$CONF6/$PORT/disable_ipv6
|
||||
fi
|
||||
if wifi_running; then REPLY="Joined"; else REPLY="Failed"; fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
wifi_restart(){
|
||||
log "Restarting $DAEMON..."
|
||||
wifi_stop
|
||||
sleep 1
|
||||
wifi_start
|
||||
}
|
||||
|
||||
wifi_status(){
|
||||
if wifi_running; then
|
||||
echo "$DAEMON is currently connected."
|
||||
else
|
||||
echo "$DAEMON is not connected."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
wifi_start
|
||||
;;
|
||||
'stop')
|
||||
wifi_stop
|
||||
;;
|
||||
'join')
|
||||
wifi_join
|
||||
;;
|
||||
'restart')
|
||||
wifi_restart
|
||||
;;
|
||||
'status')
|
||||
wifi_status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $BASENAME start|stop|join|restart|status"
|
||||
exit 1
|
||||
esac
|
||||
exit 0
|
||||
+14
-7
@@ -2,8 +2,8 @@
|
||||
#
|
||||
# script: create_network_ini
|
||||
#
|
||||
# Copyright 2005-2023, Lime Technology
|
||||
# Copyright 2012-2023, Bergware International.
|
||||
# Copyright 2005-2025, Lime Technology
|
||||
# Copyright 2012-2025, Bergware International.
|
||||
#
|
||||
# create initial network.ini file on system start
|
||||
# create system welcome message
|
||||
@@ -235,17 +235,24 @@ if [[ -n $DATA && -e /var/run/nginx.socket ]]; then
|
||||
fi
|
||||
|
||||
# generate our welcome text (management interface only)
|
||||
if [[ -z $interface || "eth0 br0 bond0" =~ $interface ]]; then
|
||||
if [[ -z $interface || "eth0 br0 bond0 wlan0" =~ $interface ]]; then
|
||||
. /etc/unraid-version
|
||||
echo -e "Unraid Server OS version: $version" >/etc/issue
|
||||
# find management interface
|
||||
[[ -e /sys/class/net/bond0 ]] && dev=bond0 || dev=eth0
|
||||
[[ -e /sys/class/net/br0 ]] && dev=br0
|
||||
IPv4=$(ip -br -4 addr show $dev scope global|sed -r 's/metric [0-9]+//g'|awk '{print $3;exit}')
|
||||
IPv6=$(ip -br -6 addr show $dev scope global|sed -r 's/metric [0-9]+//g'|awk '{print $NF;exit}')
|
||||
IPv4=$(ip -br -4 addr show $dev scope global | sed -r 's/\/[0-9]+//g' | awk '{print $3;exit}')
|
||||
IPv6=$(ip -br -6 addr show $dev scope global -temporary -deprecated | sed -r 's/\/[0-9]+//g' | awk '{print $3;exit}')
|
||||
# show current IP assignment
|
||||
[[ -n $IPv4 ]] && echo " IPv4 address: ${IPv4%/*}" >>/etc/issue || echo " IPv4 address: not set" >>/etc/issue
|
||||
[[ -n $IPv6 ]] && echo " IPv6 address: ${IPv6%/*}" >>/etc/issue || echo " IPv6 address: not set" >>/etc/issue
|
||||
[[ -n $IPv4 ]] && echo " IPv4 address: $IPv4" >>/etc/issue || echo " IPv4 address: not set" >>/etc/issue
|
||||
[[ -n $IPv6 ]] && echo " IPv6 address: $IPv6" >>/etc/issue || echo " IPv6 address: not set" >>/etc/issue
|
||||
if [[ -e /sys/class/net/wlan0 ]]; then
|
||||
echo "Wireless network:" >>/etc/issue
|
||||
IPv4=$(ip -br -4 addr show wlan0 scope global | sed -r 's/\/[0-9]+//g' | awk '{print $3;exit}')
|
||||
IPv6=$(ip -br -6 addr show wlan0 scope global -temporary -deprecated | sed -r 's/\/[0-9]+//g' | awk '{print $3;exit}')
|
||||
[[ -n $IPv4 ]] && echo " IPv4 address: $IPv4" >>/etc/issue || echo " IPv4 address: not set" >>/etc/issue
|
||||
[[ -n $IPv6 ]] && echo " IPv6 address: $IPv6" >>/etc/issue || echo " IPv6 address: not set" >>/etc/issue
|
||||
fi
|
||||
echo >>/etc/issue
|
||||
fi
|
||||
exit 0
|
||||
|
||||
Reference in New Issue
Block a user