diff --git a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page index 91552272c8..abc663b9ec 100644 --- a/emhttp/plugins/dynamix.docker.manager/DockerSettings.page +++ b/emhttp/plugins/dynamix.docker.manager/DockerSettings.page @@ -20,12 +20,9 @@ Tag="icon-docker" // Add the Docker JSON client require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php"; -$DockerClient = new DockerClient(); +$DockerClient = new DockerClient(); exec("/etc/rc.d/rc.docker status >/dev/null",$dummy,$DockerStopped); -exec("ls --indicator-style=none /sys/class/net|awk '/^br[0-9]+$/'",$nics); -$bridge = count($nics)>0; - function strposX($s, $c, $n=1) { $p = 0; while ($n && $p=strpos($s,$c,$p)!==false) {$n--; $p+=strlen($c);} @@ -34,22 +31,29 @@ function strposX($s, $c, $n=1) { unset($custom,$other); exec("ls --indicator-style=none /sys/class/net|grep -P '^br[0-9]'",$custom); -exec("ls --indicator-style=none /sys/class/net|grep -P '^(bond|eth)[0-9]'",$other); +exec("ls --indicator-style=none /sys/class/net|grep -P '^(bond|eth|wlan)[0-9]'",$other); +$bridge = count($custom)>0; $slaves = []; + foreach ($other as $network) { if (substr($network,0,4)=='bond') { $br = str_replace('bond','br',$network); $bond = "/sys/class/net/$network/bonding/slaves"; if (file_exists($bond)) $slaves = array_merge($slaves,explode(' ',str_replace("\n","",file_get_contents($bond)))); if (!in_array($br,$custom)) $custom[] = $network; - } else { + } elseif (substr($network,0,3)=='eth') { $br = str_replace('eth','br',$network); $bond = str_replace('eth','bond',$network); if (!in_array($br,$custom) && !in_array($bond,$custom)) $custom[] = $network; + } else { + $custom[] = $network; } } -$include = $include6 = $address = $address6 = $gateway = $gateway6 = $unset = $protocol = []; -$wide = false; + +$include = $include6 = $address = $address6 = $gateway = $gateway6 = $unset = $protocol = []; +$wide = false; +$wlan = (array)@parse_ini_file('/var/local/emhttp/wireless.ini'); + foreach ($custom as $network) { if (in_array($network,$slaves)) continue; $ip4 = exec("ip -4 -br addr show $network scope global | awk '{print $3;exit}'"); @@ -58,12 +62,16 @@ foreach ($custom as $network) { $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) { - $protocol[$network] = _var($$eth,'PROTOCOL:0','ipv4'); + if (substr($network,0,4) != 'wlan') { + [$eth,$vlan] = my_explode('.',$network); + $eth = str_replace(['bond','br'],'eth',$eth); + if (!$vlan) { + $protocol[$network] = _var($$eth,'PROTOCOL:0','ipv4'); + } else { + foreach ($$eth as $key => $value) if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol[$network] = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} + } } else { - foreach ($$eth as $key => $value) if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol[$network] = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} + $protocol[$network] = empty($wlan['IP6']) ? 'ipv4' : 'ipv4+ipv6'; } if ($ip4 && $route4) { $include[$network] = $route4; @@ -89,22 +97,34 @@ $unset = array_unique($unset); function normalize($network) { return strtoupper(str_replace('.','_',$network)); } + function base_min($route) { [$net,$mask] = my_explode('/',$route); $mask = 32-$mask; return explode('.',long2ip((ip2long($net)>>$mask)<<$mask)); } + function base_max($route) { [$net,$mask] = my_explode('/',$route); $mask = 32-$mask; return explode('.',long2ip(((ip2long($net)>>$mask)<<$mask)+pow(2,$mask)-1)); } + function base_net($route) { return substr(explode('/',$route)[0],0,-2); } +function hide_wlan($network) { + return $network=='wlan0' && lan_port(DockerUtil::port(),true)==1; +} + +function hide_eth($network) { + $mgmt_port = ['br0','bond0','eth0']; + return in_array($network,$mgmt_port) && lan_port('wlan0',true)==1; +} + $bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c'; -//Check if docker.cfg not exists +//Check if docker.cfg does exist $no_dockercfg = !is_file('/boot/config/docker.cfg'); ?> @@ -285,16 +305,20 @@ _(Preserve user defined networks)_: $net = normalize($network); $docker_auto = "DOCKER_AUTO_$net"; $docker_dhcp = "DOCKER_DHCP_$net"; +$hide_wlan = hide_wlan($network); ?> - + +
+ + _(IPv4 custom network on interface)_ (_(optional)_): (_(optional)_): echo ""; ?> + +
+ + :docker_include_interface_vlan_ipv4_help: @@ -342,11 +370,15 @@ _(IPv4 custom network on interface)_ (_(optional)_): + +
+ _(IPv4 custom network on interface)_ (_(optional)_): : > @@ -361,6 +393,9 @@ _(IPv4 custom network on interface)_ (_(optional)_): ( _(hosts)_) + + +
@@ -373,9 +408,13 @@ _(IPv4 custom network on interface)_ (_(optional)_): $route):?> + +
+ _(IPv6 custom network on interface)_ (_(optional)_): (_(optional)_): **_(Subnet)_:** **_(Gateway)_:** + +
+ :docker_include_interface_vlan_ipv6_help: @@ -402,11 +444,15 @@ _(IPv6 custom network on interface)_ (_(optional)_): + +
+ _(IPv6 custom network on interface)_ (_(optional)_): : > @@ -415,6 +461,9 @@ _(IPv6 custom network on interface)_ (_(optional)_): **_(Gateway)_:**" title="_(IPv6 address nnnn:xxxx::yyyy)_"> + +
+ @@ -424,7 +473,6 @@ _(IPv6 custom network on interface)_ (_(optional)_): - _(Docker version)_: : getInfo(); echo $arrInfo['Version']?> @@ -473,72 +521,117 @@ _(Preserve user defined networks)_: $route):?> + +
+ + _(IPv4 custom network on interface)_ : : **_(Subnet)_:** **_(Gateway)_:** **_(DHCP pool)_:**   ( _(hosts)_) + +
+ $value) { - if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} +$port = normalize($network); +$hide_eth = hide_eth($network); + +if (substr($network,0,4) != 'wlan') { + [$eth,$vlan] = my_explode('.',$network); + $eth = str_replace(['bond','br'],'eth',$eth); + if (!$vlan) { + $protocol = _var($$eth,'PROTOCOL:0','ipv4'); + } else { + foreach ($$eth as $key => $value) { + if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} + } } +} else { + $protocol = empty($wlan['IP6']) ? 'ipv4' : 'ipv4+ipv6'; } + [$subnet,$mask] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET_$port")); [$range,$size] = my_explode('/',_var($dockercfg,"DOCKER_RANGE_$port")); ?> + +
+ + _(IPv4 custom network on interface)_ : : **_(Subnet)_:** / **_(Gateway)_:** **_(DHCP pool)_:**   ( _(hosts)_) + +
+ $route):?> + +
+ + _(IPv6 custom network on interface)_ : : **_(Subnet)_:** **_(Gateway)_:** + +
+ $value) { - if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} +$port = normalize($network); +$hide_eth = hide_eth($network); + +if (substr($network,0,4) != 'wlan') { + [$eth,$vlan] = my_explode('.',$network); + $eth = str_replace(['bond','br'],'eth',$eth); + if (!$vlan) { + $protocol = _var($$eth,'PROTOCOL:0','ipv4'); + } else { + foreach ($$eth as $key => $value) { + if (strpos($key,'VLANID')!==false && $value==$vlan) {$protocol = _var($$eth,str_replace('VLANID','PROTOCOL',$key),'ipv4'); break;} + } } +} else { + $protocol = empty($wlan['IP6']) ? 'ipv4' : 'ipv4+ipv6'; } + [$subnet6,$mask6] = my_explode('/',_var($dockercfg,"DOCKER_SUBNET6_$port")); [$range6,$size6] = my_explode('/',_var($dockercfg,"DOCKER_RANGE6_$port")); ?> + +
+ + _(IPv6 custom network on interface)_ : : **_(Subnet)_:** / **_(Gateway)_:** + +
+ @@ -910,7 +1003,7 @@ function updateLocation(val) { } } function updateBackingFS(val) { - var backingfs = ""; + var backingfs = ""; var warning = document.getElementById("WARNING_BACKINGFS"); var checkbox = $(".deleteCheckbox"); if (val !== backingfs) { diff --git a/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php b/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php index 6f8d0a981a..ef636c2c58 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php +++ b/emhttp/plugins/dynamix.docker.manager/include/CreateDocker.php @@ -1092,10 +1092,12 @@ function prepareCategory() { [$eth,$x] = my_explode('.',$network); $eth = str_replace(['br','bond'],'eth',$eth); $n = $x ? 1 : 0; while (isset($$eth["VLANID:$n"]) && $$eth["VLANID:$n"] != $x) $n++; - if ($$eth["DESCRIPTION:$n"]) $name .= ' -- '.compress(trim($$eth["DESCRIPTION:$n"])); + if (!empty($$eth["DESCRIPTION:$n"])) $name .= ' -- '.compress(trim($$eth["DESCRIPTION:$n"])); } elseif (preg_match('/^wg[0-9]+$/',$network)) { $conf = file("/etc/wireguard/$network.conf"); if ($conf[1][0]=='#') $name .= ' -- '.compress(trim(substr($conf[1],1))); + } elseif (substr($network,0,4)=='wlan') { + $name .= ' -- '._('Wireless interface'); } ?> diff --git a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php index 5375e1ff5e..cc979e715b 100644 --- a/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php +++ b/emhttp/plugins/dynamix.docker.manager/include/DockerClient.php @@ -40,8 +40,11 @@ // Docker configuration file - guaranteed to exist $docker_cfgfile = '/boot/config/docker.cfg'; +$mgmt_port = ['br0','bond0','eth0']; + if (file_exists($docker_cfgfile)) { - $port = strtoupper(DockerUtil::port()); + $port = DockerUtil::port(); + $port = strtoupper((in_array($port,$mgmt_port) && lan_port($port,true)==0) ? 'wlan0' : $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 @@ -49,7 +52,7 @@ } } -$defaults = (array)@parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg"); +$defaults = (array)@parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg"); $dockercfg = array_replace_recursive($defaults, (array)@parse_ini_file($docker_cfgfile)); function var_split($item, $i=0) { @@ -1078,15 +1081,12 @@ public function getDockerImages() { ################################## class DockerUtil { - public static function ensureImageTag($image): string - { + public static function ensureImageTag($image): string { extract(static::parseImageTag($image)); - return "$strRepo:$strTag"; } - public static function parseImageTag($image): array - { + public static function parseImageTag($image): array { if (strpos($image, 'sha256:') === 0) { // sha256 was provided instead of actual repo name so truncate it for display: $strRepo = substr($image, 7, 12); @@ -1102,21 +1102,17 @@ public static function parseImageTag($image): array $strRepo = $image; } } - // Add :latest tag to image if it's absent if (empty($strTag)) $strTag = 'latest'; - return array_map('trim', ['strRepo' => $strRepo, 'strTag' => $strTag]); } - private static function splitImage($image): ?array - { + private static function splitImage($image): ?array { if (false === preg_match('@^(.+/)*([^/:]+)(:[^:/]*)*$@', $image, $newSections) || count($newSections) < 3) { return null; } else { [, $strRepo, $image, $strTag] = array_merge($newSections, ['']); $strTag = str_replace(':','',$strTag??''); - return [ 'strRepo' => $strRepo . $image, 'strTag' => $strTag, diff --git a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php index 024b0f21e4..c3974014d9 100644 --- a/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php +++ b/emhttp/plugins/dynamix.vm.manager/templates/Custom.form.php @@ -1484,9 +1484,7 @@