From 4b8251c988868f2d6fbd6375092199110e2443b2 Mon Sep 17 00:00:00 2001
From: Matthias Schiffer <mschiffer@universe-factory.net>
Date: Sun, 23 Jan 2022 13:39:35 +0100
Subject: [PATCH] gluon-core: initialize interfaces role configuration

The new configuration generates sections iface_single/lan/wan in
/etc/config/gluon. These sections usually refer to a sysconfig-controlled
interface list, but adding custom sections with verbatim interfaces names
is also possible.

Each interface section contains a list of roles. The supported roles are
'client', 'uplink' and 'mesh'. Multiple roles can be configured on the
same interface (for example the old 'mesh_on_wan' setting would become
'uplink'+'mesh').

'client' is subsumed by any other role configured on the same interface
('client'+'mesh' is equivalent to 'mesh'). This property is important, as
it allows the Wired Mesh settings in gluon-web-network to simply add and
remove the mesh role without having to care what other roles are set -
so in the default setup, this would switch between 'client' and
'client'+'mesh' for the LAN interface.

By default, the WAN interface has role 'uplink' and the LAN interface
'client'; if only a single interface exists, the roles from the WAN
interface are used by default. The default for each of the three
interfaces (WAN/LAN/single) can be changed separated in site.conf,
superseding the old mesh_on_wan, mesh_on_lan and single_as_lan settings.
---
 package/gluon-core/check_site.lua             | 11 +++-
 .../lib/gluon/upgrade/021-interface-roles     | 66 +++++++++++++++++++
 2 files changed, 74 insertions(+), 3 deletions(-)
 create mode 100755 package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles

diff --git a/package/gluon-core/check_site.lua b/package/gluon-core/check_site.lua
index 4cb44d5b..103cb929 100644
--- a/package/gluon-core/check_site.lua
+++ b/package/gluon-core/check_site.lua
@@ -74,6 +74,11 @@ need_string_match(in_domain({'next_node', 'ip4'}), '^%d+.%d+.%d+.%d+$', false)
 
 need_boolean(in_domain({'mesh', 'vxlan'}), false)
 
-need_boolean(in_site({'mesh_on_wan'}), false)
-need_boolean(in_site({'mesh_on_lan'}), false)
-need_boolean(in_site({'single_as_lan'}), false)
+local interfaces_roles = {'client', 'uplink', 'mesh'}
+for _, config in ipairs({'wan', 'lan', 'single'}) do
+	need_array_of(in_site({'interfaces', config, 'default_roles'}), interfaces_roles, false)
+end
+
+obsolete({'mesh_on_wan'}, 'Use interfaces.wan.default_roles.')
+obsolete({'mesh_on_lan'}, 'Use interfaces.lan.default_roles.')
+obsolete({'single_as_lan'}, 'Use interfaces.single.default_roles.')
diff --git a/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles b/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles
new file mode 100755
index 00000000..182c8903
--- /dev/null
+++ b/package/gluon-core/luasrc/lib/gluon/upgrade/021-interface-roles
@@ -0,0 +1,66 @@
+#!/usr/bin/lua
+
+local site = require 'gluon.site'
+local sysconfig = require 'gluon.sysconfig'
+local uci = require('simple-uci').cursor()
+local util = require 'gluon.util'
+
+-- Defaults from site.conf
+local roles = {
+	lan = site.interfaces.lan.roles({'client'}),
+	wan = site.interfaces.wan.roles({'uplink'}),
+}
+roles.single = site.interfaces.single.roles(roles.wan)
+
+-- Migration of Mesh-on-WAN/LAN setting from Gluon 2021.1 and older (to be removed in 2024)
+--
+-- Wired meshing is enabled for single interfaces if either of the settings
+-- was previously enabled
+local mesh_lan_disabled = uci:get('network_gluon-old', 'mesh_lan', 'disabled')
+local mesh_wan_disabled = uci:get('network_gluon-old', 'mesh_wan', 'disabled')
+if mesh_wan_disabled == '0' then
+	util.add_to_set(roles.wan, 'mesh')
+	util.add_to_set(roles.single, 'mesh')
+elseif mesh_wan_disabled == '1' then
+	util.remove_from_set(roles.wan, 'mesh')
+	util.remove_from_set(roles.single, 'mesh')
+end
+if mesh_lan_disabled == '0' then
+	util.add_to_set(roles.lan, 'mesh')
+	util.add_to_set(roles.single, 'mesh')
+elseif mesh_lan_disabled == '1' then
+	util.remove_from_set(roles.lan, 'mesh')
+	util.remove_from_set(roles.single, 'mesh')
+end
+
+-- Migration of single to WAN/LAN or vice-versa (an interface was added or removed)
+-- We identify the WAN with the single interface in this case
+--
+-- These settings only take effect when the section that is the target of the
+-- migration does not exist yet.
+if uci:get('gluon', 'iface_wan') then
+	roles.single = uci:get_list('gluon', 'iface_wan', 'role')
+end
+if uci:get('gluon', 'iface_single') then
+	roles.wan = uci:get_list('gluon', 'iface_single', 'role')
+end
+
+-- Non-existing interfaces are nil, so they will not be added to the table
+local interfaces = {
+	lan = sysconfig.lan_ifname,
+	wan = sysconfig.wan_ifname,
+	single = sysconfig.single_ifname,
+}
+
+for iface in pairs(interfaces) do
+	local section_name = 'iface_' .. iface
+	if not uci:get('gluon', section_name) then
+		uci:section('gluon', 'interface', section_name, {
+			-- / prefix refers to sysconfig ifnames
+			name = '/' .. iface,
+			role = roles[iface],
+		})
+	end
+end
+
+uci:save('gluon')
-- 
GitLab