gluon-{config,web}-*: show "save & apply" button during runtime

If the user has left the setup mode and starts a uhttpd instance to
serve the config mode during normal runtime of the gluon node, this
change is helpful. Instead of the "Save" or "Save & reboot" button,
now a "Save & apply" button is presented. If this button is pressed,
"gluon-reload" including a "gluon-reconfigure" is invoked internally
causing the node to regenerate and reload its configuration
immediately.

Currently such an uhttpd instance is not running by default, but a
user can start such an instance manually and access it via ssh port
forwarding.
This commit is contained in:
Leonardo Mörlein 2021-04-22 23:38:07 +02:00
parent b72588a014
commit 04848dbd36
41 changed files with 223 additions and 13 deletions

View File

@ -13,6 +13,9 @@ msgstr ""
msgid "Save & restart" msgid "Save & restart"
msgstr "Speichern & Neustarten" msgstr "Speichern & Neustarten"
msgid "Save & apply"
msgstr "Speichern & Anwenden"
msgid "Welcome!" msgid "Welcome!"
msgstr "Willkommen!" msgstr "Willkommen!"

View File

@ -13,6 +13,9 @@ msgstr ""
msgid "Save & restart" msgid "Save & restart"
msgstr "Enregistrer & Redémarer" msgstr "Enregistrer & Redémarer"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"
msgid "Welcome!" msgid "Welcome!"
msgstr "Bienvenue!" msgstr "Bienvenue!"

View File

@ -4,6 +4,9 @@ msgstr "Content-Type: text/plain; charset=UTF-8"
msgid "Save & restart" msgid "Save & restart"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""
msgid "Welcome!" msgid "Welcome!"
msgstr "" msgstr ""

View File

@ -11,7 +11,12 @@ for _, entry in ipairs(util.glob('/lib/gluon/config-mode/wizard/*')) do
end end
local f = Form(translate("Welcome!")) local f = Form(translate("Welcome!"))
f.submit = translate('Save & restart')
if util.in_setup_mode() then
f.submit = translate('Save & restart')
else
f.submit = translate('Save & apply')
end
f.reset = false f.reset = false
local s = f:section(Section) local s = f:section(Section)
@ -48,8 +53,10 @@ function f:write()
r() r()
end end
f.template = "wizard/reboot"
f.package = "gluon-config-mode-core" f.package = "gluon-config-mode-core"
if util.in_setup_mode() then
f.template = "wizard/reboot"
f.hidenav = true f.hidenav = true
if unistd.fork() == 0 then if unistd.fork() == 0 then
@ -63,6 +70,9 @@ function f:write()
unistd.execp('reboot', {[0] = 'reboot'}) unistd.execp('reboot', {[0] = 'reboot'})
end end
else
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -54,7 +54,7 @@ return function(form, uci)
function o:write(data) function o:write(data)
if data ~= selected_domain then if data ~= selected_domain then
domain_changed = true domain_changed = true
uci:set('gluon', 'core', 'domain', data) uci:set('gluon', 'core', 'switch_domain', data)
end end
end end

View File

@ -32,5 +32,11 @@ return function(form, uci)
pretty_hostname.set(uci, data or default_hostname) pretty_hostname.set(uci, data or default_hostname)
end end
return {'system'} local function reload_hostname()
local hostname_file = io.open('/proc/sys/kernel/hostname', 'w')
hostname_file:write(o.data or default_hostname)
hostname_file:close()
end
return {'system', reload_hostname}
end end

View File

@ -1,9 +1,12 @@
local bit = require 'bit' local bit = require 'bit'
local posix_glob = require 'posix.glob' local posix_glob = require 'posix.glob'
local posix_syslog = require 'posix.syslog' local posix_syslog = require 'posix.syslog'
local posix_stat = require 'posix.sys.stat'
local hash = require 'hash' local hash = require 'hash'
local sysconfig = require 'gluon.sysconfig' local sysconfig = require 'gluon.sysconfig'
local site = require 'gluon.site' local site = require 'gluon.site'
local fcntl = require 'posix.fcntl'
local unistd = require 'posix.unistd'
local M = {} local M = {}
@ -188,4 +191,28 @@ function M.log(message, verbose)
posix_syslog.syslog(posix_syslog.LOG_INFO, message) posix_syslog.syslog(posix_syslog.LOG_INFO, message)
end end
function M.in_setup_mode()
return (posix_stat.stat('/var/gluon/setup-mode') ~= nil)
end
function M.reconfigure_asynchronously()
local uci = require('simple-uci').cursor()
uci:set('gluon', 'core', 'reconfigure', true)
uci:save('gluon')
uci:commit('gluon')
-- as this may take a while, we fork here.
if unistd.fork() == 0 then
-- Replace stdout with /dev/null
local null = fcntl.open('/dev/null', fcntl.O_WRONLY)
unistd.dup2(null, unistd.STDOUT_FILENO)
-- Sleep a little so the browser can fetch everything required to
-- display the reboot page, then reboot the device.
unistd.sleep(1)
unistd.execp('gluon-reload', {[0] = 'gluon-reload'})
end
end
return M return M

View File

@ -133,3 +133,6 @@ msgstr "Hier kannst du ein manuelles Firmwareupdate durchführen."
msgid "You can provide your SSH keys here (one per line):" msgid "You can provide your SSH keys here (one per line):"
msgstr "" msgstr ""
"Hier hast du die Möglichkeit, SSH-Keys zu hinterlegen (einen pro Zeile):" "Hier hast du die Möglichkeit, SSH-Keys zu hinterlegen (einen pro Zeile):"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -133,3 +133,6 @@ msgstr "Ici vous pouvez changer manuellement votre firmware."
msgid "You can provide your SSH keys here (one per line):" msgid "You can provide your SSH keys here (one per line):"
msgstr "Ici vous pouvez entrer vos clés SSH (une par ligne):" msgstr "Ici vous pouvez entrer vos clés SSH (une par ligne):"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -115,3 +115,6 @@ msgstr ""
msgid "You can provide your SSH keys here (one per line):" msgid "You can provide your SSH keys here (one per line):"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -18,6 +18,11 @@ local unistd = require 'posix.unistd'
local wait = require 'posix.sys.wait' local wait = require 'posix.sys.wait'
local f_keys = Form(translate("SSH keys"), translate("You can provide your SSH keys here (one per line):"), 'keys') local f_keys = Form(translate("SSH keys"), translate("You can provide your SSH keys here (one per line):"), 'keys')
if not util.in_setup_mode() then
f_keys.submit = translate('Save & apply')
end
local s = f_keys:section(Section) local s = f_keys:section(Section)
local keys = s:option(TextValue, "keys") local keys = s:option(TextValue, "keys")
keys.wrap = "off" keys.wrap = "off"
@ -33,6 +38,10 @@ function keys:write(value)
else else
unistd.unlink("/etc/dropbear/authorized_keys") unistd.unlink("/etc/dropbear/authorized_keys")
end end
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
local config = site.config_mode.remote_login local config = site.config_mode.remote_login
@ -57,6 +66,10 @@ local f_password = Form(translate("Password"), translate(
) )
f_password.reset = false f_password.reset = false
if not util.in_setup_mode() then
f_password.submit = translate('Save & apply')
end
s = f_password:section(Section) s = f_password:section(Section)
local pw1 = s:option(Value, "pw1", translate("Password")) local pw1 = s:option(Value, "pw1", translate("Password"))
@ -126,6 +139,10 @@ function f_password:write()
os.execute('passwd -l root >/dev/null') os.execute('passwd -l root >/dev/null')
f_password.message = translate("Password removed.") f_password.message = translate("Password removed.")
end end
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f_keys, f_password return f_keys, f_password

View File

@ -18,3 +18,6 @@ msgstr "Branch"
msgid "Enable" msgid "Enable"
msgstr "Aktivieren" msgstr "Aktivieren"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -18,3 +18,6 @@ msgstr "Branche"
msgid "Enable" msgid "Enable"
msgstr "Activer" msgstr "Activer"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -9,3 +9,6 @@ msgstr ""
msgid "Enable" msgid "Enable"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -10,8 +10,14 @@ You may obtain a copy of the License at
local uci = require("simple-uci").cursor() local uci = require("simple-uci").cursor()
local autoupdater = uci:get_first("autoupdater", "autoupdater") local autoupdater = uci:get_first("autoupdater", "autoupdater")
local util = require 'gluon.util'
local f = Form(translate("Automatic updates")) local f = Form(translate("Automatic updates"))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
local s = f:section(Section) local s = f:section(Section)
local o local o
@ -41,6 +47,10 @@ end
function f:write() function f:write()
uci:commit("autoupdater") uci:commit("autoupdater")
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -22,3 +22,6 @@ msgstr "Logging"
msgid "Port" msgid "Port"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -18,3 +18,6 @@ msgstr ""
msgid "Port" msgid "Port"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -1,11 +1,17 @@
local uci = require('simple-uci').cursor() local uci = require('simple-uci').cursor()
local system = uci:get_first('system', 'system') local system = uci:get_first('system', 'system')
local util = require 'gluon.util'
local f = Form(translate('Logging'), translate( local f = Form(translate('Logging'), translate(
"If you want to use a remote syslog server, you can set it up here. " "If you want to use a remote syslog server, you can set it up here. "
.. "Please keep in mind that the data is not encrypted, which may cause " .. "Please keep in mind that the data is not encrypted, which may cause "
.. "individual-related data to be transmitted unencrypted over the internet." .. "individual-related data to be transmitted unencrypted over the internet."
)) ))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
local s = f:section(Section) local s = f:section(Section)
local enable = s:option(Flag, 'log_remote', translate('Enable')) local enable = s:option(Flag, 'log_remote', translate('Enable'))
@ -36,6 +42,10 @@ end
function f:write() function f:write()
uci:commit('system') uci:commit('system')
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -36,3 +36,6 @@ msgstr "Hohe Geschwindigkeit"
msgid "Security mode" msgid "Security mode"
msgstr "Hohe Sicherheit" msgstr "Hohe Sicherheit"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -36,3 +36,6 @@ msgstr "Mode performance"
msgid "Security mode" msgid "Security mode"
msgstr "Mode sécurité" msgstr "Mode sécurité"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -21,3 +21,6 @@ msgstr ""
msgid "Security mode" msgid "Security mode"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -3,6 +3,10 @@ local util = require 'gluon.util'
local f = Form(translate('Mesh VPN')) local f = Form(translate('Mesh VPN'))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
local s = f:section(Section) local s = f:section(Section)
local mode = s:option(Value, 'mode') local mode = s:option(Value, 'mode')
@ -37,6 +41,10 @@ function mode:write(data)
uci:save('fastd') uci:save('fastd')
uci:commit('fastd') uci:commit('fastd')
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -15,3 +15,6 @@ msgstr "Zurücksetzen"
msgid "Save" msgid "Save"
msgstr "Speichern" msgstr "Speichern"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -15,3 +15,6 @@ msgstr "Remise à zéro"
msgid "Save" msgid "Save"
msgstr "Soumettre" msgstr "Soumettre"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -6,3 +6,6 @@ msgstr ""
msgid "Save" msgid "Save"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -60,3 +60,6 @@ msgstr "Statische DNS-Server"
msgid "WAN connection" msgid "WAN connection"
msgstr "WAN-Verbindung" msgstr "WAN-Verbindung"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -60,3 +60,6 @@ msgstr "Adresse DNS statique"
msgid "WAN connection" msgid "WAN connection"
msgstr "Connexion WAN" msgstr "Connexion WAN"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -51,3 +51,6 @@ msgstr ""
msgid "WAN connection" msgid "WAN connection"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -18,6 +18,10 @@ local dns_static = uci:get_first("gluon-wan-dnsmasq", "static")
local f = Form(translate("WAN connection")) local f = Form(translate("WAN connection"))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
local s = f:section(Section) local s = f:section(Section)
local ipv4 = s:option(ListValue, "ipv4", translate("IPv4")) local ipv4 = s:option(ListValue, "ipv4", translate("IPv4"))
@ -163,6 +167,10 @@ function f:write()
uci:commit("network") uci:commit("network")
uci:commit('system') uci:commit('system')
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -25,3 +25,6 @@ msgstr "Verwendungszweck"
msgid "Role" msgid "Role"
msgstr "Rolle" msgstr "Rolle"
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -25,3 +25,6 @@ msgstr "Rôle du nœud"
msgid "Role" msgid "Role"
msgstr "Rôle" msgstr "Rôle"
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -12,3 +12,6 @@ msgstr ""
msgid "Role" msgid "Role"
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -2,6 +2,7 @@ local f, s, o
local site = require 'gluon.site' local site = require 'gluon.site'
local site_i18n = i18n 'gluon-site' local site_i18n = i18n 'gluon-site'
local uci = require("simple-uci").cursor() local uci = require("simple-uci").cursor()
local util = require 'gluon.util'
local config = 'gluon-node-info' local config = 'gluon-node-info'
-- where to read the configuration from -- where to read the configuration from
@ -9,6 +10,10 @@ local role = uci:get(config, uci:get_first(config, "system"), "role")
f = Form(translate("Node role")) f = Form(translate("Node role"))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
s = f:section(Section, nil, translate( s = f:section(Section, nil, translate(
"If this node has a special role within the mesh network you can specify this role here. " "If this node has a special role within the mesh network you can specify this role here. "
.. "Please find out about the available roles and their impact first. " .. "Please find out about the available roles and their impact first. "
@ -24,6 +29,10 @@ end
function o:write(data) function o:write(data)
uci:set(config, uci:get_first(config, "system"), "role", data) uci:set(config, uci:get_first(config, "system"), "role", data)
uci:commit(config) uci:commit(config)
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -60,3 +60,6 @@ msgstr ""
"Funktionalität ist völlig unabhängig von den Mesh-Funktionen des Knotens. " "Funktionalität ist völlig unabhängig von den Mesh-Funktionen des Knotens. "
"Beachte, dass du nicht gleichzeitig das Meshen über den WAN-Port aktiviert " "Beachte, dass du nicht gleichzeitig das Meshen über den WAN-Port aktiviert "
"haben solltest." "haben solltest."
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -59,3 +59,6 @@ msgstr ""
"Fi séparé. Cette fonction est complètement indépendante de les fonctions de " "Fi séparé. Cette fonction est complètement indépendante de les fonctions de "
"MESH. Il ne faut pas activer la fonction de MESH et de Wi-Fi privé en même " "MESH. Il ne faut pas activer la fonction de MESH et de Wi-Fi privé en même "
"temps." "temps."
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -46,3 +46,6 @@ msgid ""
"the mesh functionality. Please note that the private WLAN and meshing on the " "the mesh functionality. Please note that the private WLAN and meshing on the "
"WAN interface should not be enabled at the same time." "WAN interface should not be enabled at the same time."
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -1,12 +1,17 @@
local uci = require("simple-uci").cursor() local uci = require("simple-uci").cursor()
local platform = require 'gluon.platform' local platform = require 'gluon.platform'
local wireless = require 'gluon.wireless' local wireless = require 'gluon.wireless'
local util = require 'gluon.util'
-- where to read the configuration from -- where to read the configuration from
local primary_iface = 'wan_radio0' local primary_iface = 'wan_radio0'
local f = Form(translate("Private WLAN")) local f = Form(translate("Private WLAN"))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
local s = f:section(Section, nil, translate( local s = f:section(Section, nil, translate(
'Your node can additionally extend your private network by bridging the WAN interface ' 'Your node can additionally extend your private network by bridging the WAN interface '
.. 'with a separate WLAN. This feature is completely independent of the mesh functionality. ' .. 'with a separate WLAN. This feature is completely independent of the mesh functionality. '
@ -77,6 +82,10 @@ function f:write()
end) end)
uci:commit('wireless') uci:commit('wireless')
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f

View File

@ -77,3 +77,6 @@ msgstr ""
"werden. Wenn möglich, ist in den Werten der Sendeleistung der Antennengewinn " "werden. Wenn möglich, ist in den Werten der Sendeleistung der Antennengewinn "
"enthalten; diese Werte sind allerdings für viele Geräte nicht verfügbar oder " "enthalten; diese Werte sind allerdings für viele Geräte nicht verfügbar oder "
"fehlerhaft." "fehlerhaft."
msgid "Save & apply"
msgstr "Speichern & Anwenden"

View File

@ -71,3 +71,6 @@ msgstr ""
"d'émmission se votre Wi-Fi. Prenez note que les valeurs fournies pour la " "d'émmission se votre Wi-Fi. Prenez note que les valeurs fournies pour la "
"puissance de transmission prennent en compte les gains fournis par " "puissance de transmission prennent en compte les gains fournis par "
"l'antenne, et que ces valeurs ne sont pas toujours disponibles ou exactes." "l'antenne, et que ces valeurs ne sont pas toujours disponibles ou exactes."
msgid "Save & apply"
msgstr "Enregistrer & Appliquer"

View File

@ -47,3 +47,6 @@ msgid ""
"values include the antenna gain where available, but there are many devices " "values include the antenna gain where available, but there are many devices "
"for which the gain is unavailable or inaccurate." "for which the gain is unavailable or inaccurate."
msgstr "" msgstr ""
msgid "Save & apply"
msgstr ""

View File

@ -1,6 +1,7 @@
local iwinfo = require 'iwinfo' local iwinfo = require 'iwinfo'
local uci = require("simple-uci").cursor() local uci = require("simple-uci").cursor()
local site = require 'gluon.site' local site = require 'gluon.site'
local util = require 'gluon.util'
local wireless = require 'gluon.wireless' local wireless = require 'gluon.wireless'
@ -38,6 +39,10 @@ end
local f = Form(translate("WLAN")) local f = Form(translate("WLAN"))
if not util.in_setup_mode() then
f.submit = translate('Save & apply')
end
f:section(Section, nil, translate( f:section(Section, nil, translate(
"You can enable or disable your node's client and mesh network " "You can enable or disable your node's client and mesh network "
.. "SSIDs here. Please don't disable the mesh network without " .. "SSIDs here. Please don't disable the mesh network without "
@ -201,6 +206,10 @@ function f:write()
os.execute('/lib/gluon/upgrade/200-wireless') os.execute('/lib/gluon/upgrade/200-wireless')
uci:commit('network') uci:commit('network')
uci:commit('wireless') uci:commit('wireless')
if not util.in_setup_mode() then
util.reconfigure_asynchronously()
end
end end
return f return f