Backported UCI-Dependency Tracking and Responsiveness Improvements

This commit is contained in:
Steven Barth 2008-09-07 14:17:29 +00:00
parent 0d12944af5
commit 37b79596bb
27 changed files with 305 additions and 148 deletions

View file

@ -1,4 +1,7 @@
#!/bin/sh #!/bin/sh
uci set luci.uci_oncommit.luci_statistics='/etc/init.d/luci_statistics restart' uci batch <<-EOF
uci commit luci add ucitrack luci_statistics
set ucitrack.@luci_statistics[-1].init=luci_statistics
commit ucitrack
EOF

View file

@ -1,4 +1,7 @@
#!/bin/sh #!/bin/sh
uci set luci.uci_oncommit.uvc_streamer='/sbin/luci-reload uvc-streamer' uci batch <<-EOF
uci commit luci add ucitrack uvc-streamer
set ucitrack.@uvc-streamer[-1].init=uvc-streamer
commit ucitrack
EOF

View file

@ -30,7 +30,6 @@ define Package/luci-addons/install
$(INSTALL_BIN) ./dist/usr/bin/run-parts $(1)/usr/bin $(INSTALL_BIN) ./dist/usr/bin/run-parts $(1)/usr/bin
$(INSTALL_BIN) ./dist/sbin/luci-flash $(1)/sbin $(INSTALL_BIN) ./dist/sbin/luci-flash $(1)/sbin
$(INSTALL_BIN) ./dist/sbin/luci-reload $(1)/sbin
$(INSTALL_BIN) ./dist/etc/init.d/luci_fixtime $(1)/etc/init.d $(INSTALL_BIN) ./dist/etc/init.d/luci_fixtime $(1)/etc/init.d
$(INSTALL_BIN) ./dist/etc/init.d/luci_ethers $(1)/etc/init.d $(INSTALL_BIN) ./dist/etc/init.d/luci_ethers $(1)/etc/init.d
$(INSTALL_BIN) ./dist/etc/init.d/luci_hosts $(1)/etc/init.d $(INSTALL_BIN) ./dist/etc/init.d/luci_hosts $(1)/etc/init.d

View file

@ -85,5 +85,9 @@ done
[ -n "$sysupgrade_init_conffiles" ] && do_save_conffiles [ -n "$sysupgrade_init_conffiles" ] && do_save_conffiles
run_hooks "" $sysupgrade_pre_upgrade run_hooks "" $sysupgrade_pre_upgrade
ask_bool() {
false
}
v "Switching to ramdisk..." v "Switching to ramdisk..."
run_ramfs '. /etc/functions.sh; include /lib/upgrade; do_upgrade' run_ramfs '. /etc/functions.sh; include /lib/upgrade; do_upgrade'

View file

@ -1,9 +0,0 @@
#!/bin/sh
for i in $*
do
[ -x /etc/init.d/$i ] && {
echo -n "Reloading $i... "
/etc/init.d/$i restart >/dev/null 2>&1 && echo "done." || echo "failed!"
}
done

View file

@ -69,6 +69,8 @@ a_s_fstab_swap1 = 'If your physical memory is insufficient unused data can be te
a_s_flash_flashed = 'Firmware successfully flashed. Rebooting device...' a_s_flash_flashed = 'Firmware successfully flashed. Rebooting device...'
a_s_flash_flasherr = 'Failed to flash' a_s_flash_flasherr = 'Failed to flash'
a_s_flash_fwimage = 'Firmwareimage' a_s_flash_fwimage = 'Firmwareimage'
a_s_flash_received = 'Image received. About to start flashing process. DO NOT POWER OFF THE DEVICE!'
a_s_flash_inprogress = 'Writing firmware...'
a_s_flash_fwupgrade = 'Flash Firmware' a_s_flash_fwupgrade = 'Flash Firmware'
a_s_flash_keepcfg = 'Keep configuration files' a_s_flash_keepcfg = 'Keep configuration files'
a_s_flash_notimplemented = 'Sorry, this function is not (yet) available for your platform.' a_s_flash_notimplemented = 'Sorry, this function is not (yet) available for your platform.'

View file

@ -73,6 +73,8 @@
<i18n:msg xml:id="a_s_flash_flashed">Firmware successfully flashed. Rebooting device...</i18n:msg> <i18n:msg xml:id="a_s_flash_flashed">Firmware successfully flashed. Rebooting device...</i18n:msg>
<i18n:msg xml:id="a_s_flash_flasherr">Failed to flash</i18n:msg> <i18n:msg xml:id="a_s_flash_flasherr">Failed to flash</i18n:msg>
<i18n:msg xml:id="a_s_flash_fwimage">Firmwareimage</i18n:msg> <i18n:msg xml:id="a_s_flash_fwimage">Firmwareimage</i18n:msg>
<i18n:msg xml:id="a_s_flash_received">Image received. About to start flashing process. DO NOT POWER OFF THE DEVICE!</i18n:msg>
<i18n:msg xml:id="a_s_flash_inprogress">Writing firmware...</i18n:msg>
<i18n:msg xml:id="a_s_flash_fwupgrade">Flash Firmware</i18n:msg> <i18n:msg xml:id="a_s_flash_fwupgrade">Flash Firmware</i18n:msg>
<i18n:msg xml:id="a_s_flash_keepcfg">Keep configuration files</i18n:msg> <i18n:msg xml:id="a_s_flash_keepcfg">Keep configuration files</i18n:msg>
<i18n:msg xml:id="a_s_flash_notimplemented">Sorry, this function is not (yet) available for your platform.</i18n:msg> <i18n:msg xml:id="a_s_flash_notimplemented">Sorry, this function is not (yet) available for your platform.</i18n:msg>

View file

@ -11,3 +11,4 @@ cbi_sectempty = 'This section contains no values yet'
cbi_manual = '-- custom --' cbi_manual = '-- custom --'
cbi_select = '-- Please choose --' cbi_select = '-- Please choose --'
cbi_gorel = 'Go to relevant configuration page' cbi_gorel = 'Go to relevant configuration page'
cbi_applying = 'Applying changes'

View file

@ -15,5 +15,6 @@
<i18n:msg xml:id="cbi_manual">-- custom --</i18n:msg> <i18n:msg xml:id="cbi_manual">-- custom --</i18n:msg>
<i18n:msg xml:id="cbi_select">-- Please choose --</i18n:msg> <i18n:msg xml:id="cbi_select">-- Please choose --</i18n:msg>
<i18n:msg xml:id="cbi_gorel">Go to relevant configuration page</i18n:msg> <i18n:msg xml:id="cbi_gorel">Go to relevant configuration page</i18n:msg>
<i18n:msg xml:id="cbi_applying">Applying changes</i18n:msg>
</i18n:msgs> </i18n:msgs>

View file

@ -39,6 +39,8 @@ a_s_flash = 'Upgrade'
a_s_flash_flashed = 'Flashvorgang erfolgreich. Router startet neu...' a_s_flash_flashed = 'Flashvorgang erfolgreich. Router startet neu...'
a_s_flash_flasherr = 'Flashvorgang fehlgeschlagen' a_s_flash_flasherr = 'Flashvorgang fehlgeschlagen'
a_s_flash_fwimage = 'Firmwareimage' a_s_flash_fwimage = 'Firmwareimage'
a_s_flash_received = 'Abbild empfangen. Starte Flashvorgang. SCHALTEN SIE DAS GERÄT NICHT AUS!'
a_s_flash_inprogress = 'Schreibe Firmware...'
a_s_flash_fwupgrade = 'Firmware aktualisieren' a_s_flash_fwupgrade = 'Firmware aktualisieren'
a_s_flash_keepcfg = 'Konfigurationsdateien übernehmen' a_s_flash_keepcfg = 'Konfigurationsdateien übernehmen'
a_s_flash_notimplemented = 'Diese Funktion steht leider (noch) nicht zur Verfügung.' a_s_flash_notimplemented = 'Diese Funktion steht leider (noch) nicht zur Verfügung.'

View file

@ -43,6 +43,8 @@
<i18n:msg xml:id="a_s_flash_flashed">Flashvorgang erfolgreich. Router startet neu...</i18n:msg> <i18n:msg xml:id="a_s_flash_flashed">Flashvorgang erfolgreich. Router startet neu...</i18n:msg>
<i18n:msg xml:id="a_s_flash_flasherr">Flashvorgang fehlgeschlagen</i18n:msg> <i18n:msg xml:id="a_s_flash_flasherr">Flashvorgang fehlgeschlagen</i18n:msg>
<i18n:msg xml:id="a_s_flash_fwimage">Firmwareimage</i18n:msg> <i18n:msg xml:id="a_s_flash_fwimage">Firmwareimage</i18n:msg>
<i18n:msg xml:id="a_s_flash_received">Abbild empfangen. Starte Flashvorgang. SCHALTEN SIE DAS GERÄT NICHT AUS!</i18n:msg>
<i18n:msg xml:id="a_s_flash_inprogress">Schreibe Firmware...</i18n:msg>
<i18n:msg xml:id="a_s_flash_fwupgrade">Firmware aktualisieren</i18n:msg> <i18n:msg xml:id="a_s_flash_fwupgrade">Firmware aktualisieren</i18n:msg>
<i18n:msg xml:id="a_s_flash_keepcfg">Konfigurationsdateien übernehmen</i18n:msg> <i18n:msg xml:id="a_s_flash_keepcfg">Konfigurationsdateien übernehmen</i18n:msg>
<i18n:msg xml:id="a_s_flash_notimplemented">Diese Funktion steht leider (noch) nicht zur Verfügung.</i18n:msg> <i18n:msg xml:id="a_s_flash_notimplemented">Diese Funktion steht leider (noch) nicht zur Verfügung.</i18n:msg>

View file

@ -10,3 +10,4 @@ cbi_sectempty = 'Diese Sektion enthält noch keine Einträge'
cbi_manual = '-- benutzerdefiniert --' cbi_manual = '-- benutzerdefiniert --'
cbi_select = '-- Bitte auswählen --' cbi_select = '-- Bitte auswählen --'
cbi_gorel = 'Gehe zu relevanter Konfigurationsseite' cbi_gorel = 'Gehe zu relevanter Konfigurationsseite'
cbi_applying = 'Änderungen werden angewandt'

View file

@ -14,4 +14,6 @@
<i18n:msg xml:id="cbi_manual">-- benutzerdefiniert --</i18n:msg> <i18n:msg xml:id="cbi_manual">-- benutzerdefiniert --</i18n:msg>
<i18n:msg xml:id="cbi_select">-- Bitte auswählen --</i18n:msg> <i18n:msg xml:id="cbi_select">-- Bitte auswählen --</i18n:msg>
<i18n:msg xml:id="cbi_gorel">Gehe zu relevanter Konfigurationsseite</i18n:msg> <i18n:msg xml:id="cbi_gorel">Gehe zu relevanter Konfigurationsseite</i18n:msg>
<i18n:msg xml:id="cbi_applying">Änderungen werden angewandt</i18n:msg>
</i18n:msgs> </i18n:msgs>

View file

@ -221,6 +221,7 @@ function Map.__init__(self, config, ...)
self.config = config self.config = config
self.parsechain = {self.config} self.parsechain = {self.config}
self.template = "cbi/map" self.template = "cbi/map"
self.apply_on_parse = nil
self.uci = uci.cursor() self.uci = uci.cursor()
self.save = true self.save = true
if not self.uci:load(self.config) then if not self.uci:load(self.config) then
@ -258,11 +259,18 @@ function Map.parse(self, ...)
if luci.http.formvalue("cbi.apply") then if luci.http.formvalue("cbi.apply") then
for i, config in ipairs(self.parsechain) do for i, config in ipairs(self.parsechain) do
self.uci:commit(config) self.uci:commit(config)
self.uci:apply(config)
-- Refresh data because commit changes section names -- Refresh data because commit changes section names
self.uci:load(config) self.uci:load(config)
end end
if self.apply_on_parse then
self.uci:apply(self.parsechain)
else
self._apply = function()
local cmd = self.uci:apply(self.parsechain, true)
return io.popen(cmd)
end
end
-- Reparse sections -- Reparse sections
Node.parse(self, ...) Node.parse(self, ...)
@ -274,6 +282,15 @@ function Map.parse(self, ...)
end end
end end
function Map.render(self, ...)
Node.render(self, ...)
if self._apply then
local fp = self._apply()
fp:read("*a")
fp:close()
end
end
-- Creates a child section -- Creates a child section
function Map.section(self, class, ...) function Map.section(self, class, ...)
if instanceof(class, AbstractSection) then if instanceof(class, AbstractSection) then

View file

@ -16,6 +16,19 @@ $Id$
<div class="cbi-map" id="cbi-<%=self.config%>"> <div class="cbi-map" id="cbi-<%=self.config%>">
<h1><%=self.title%></h1> <h1><%=self.title%></h1>
<div class="cbi-map-descr"><%=self.description%></div> <div class="cbi-map-descr"><%=self.description%></div>
<%- if self._apply then -%><code><%:cbi_applying%>:
<%
local fp = self._apply()
self._apply = nil
local line = fp:read()
while line do
write(line.."\n")
line = fp:read()
end
fp:close()
-%>
</code><%- end -%>
<%- self:render_children() %> <%- self:render_children() %>
<br /> <br />
</div> </div>

View file

@ -54,14 +54,17 @@ end
local Cursor = getmetatable(cursor()) local Cursor = getmetatable(cursor())
--- Applies the new config --- Applies UCI configuration changes
-- @param config UCI config -- @param configlist List of UCI configurations
function Cursor.apply(self, config) -- @param command Don't apply only return the command
local conf = require "luci.config" function Cursor.apply(self, configlist, command)
return conf.uci_oncommit[config] and configlist = self:_affected(configlist)
os.execute(conf.uci_oncommit[config] .. " >/dev/null 2>&1") local reloadcmd = "/sbin/luci-reload " .. table.concat(configlist, " ")
return command and reloadcmd or os.execute(reloadcmd .. " >/dev/null 2>&1")
end end
--- Delete all sections of a given type that match certain criteria. --- Delete all sections of a given type that match certain criteria.
-- @param config UCI config -- @param config UCI config
-- @param type UCI section type -- @param type UCI section type
@ -180,6 +183,51 @@ function Cursor.changes(self, config)
end end
-- Return a list of initscripts affected by configuration changes.
function Cursor._affected(self, configlist)
configlist = type(configlist) == "table" and configlist or {configlist}
local c = cursor()
c:load("ucitrack")
-- Resolve dependencies
local reloadlist = {}
local function _resolve_deps(name)
local reload = {name}
local deps = {}
c:foreach("ucitrack", name,
function(section)
if section.affects then
for i, aff in ipairs(section.affects) do
table.insert(deps, aff)
end
end
end)
for i, dep in ipairs(deps) do
for j, add in ipairs(_resolve_deps(dep)) do
table.insert(reload, add)
end
end
return reload
end
-- Collect initscripts
for j, config in ipairs(configlist) do
for i, e in ipairs(_resolve_deps(config)) do
if not util.contains(reloadlist, e) then
table.insert(reloadlist, e)
end
end
end
return reloadlist
end
--- Add an anonymous section. --- Add an anonymous section.
-- @class function -- @class function
-- @name Cursor.add -- @name Cursor.add

View file

@ -0,0 +1,50 @@
config network
option init network
list affects dhcp
config wireless
list affects network
config firewall
option init firewall
list affects luci-splash
list affects qos
config olsr
option init olsrd
config dhcp
option init dnsmasq
config dropbear
option init dropbear
config httpd
option init httpd
config fstab
option init fstab
config qos
option init qos
config system
option init led
config luci_ethers
option init luci_ethers
config luci_hosts
option init luci_hosts
config luci_splash
option init luci_splash
config upnpd
option init miniupnpd
config ntpclient
option init ntpclient
config samba
option init samba

32
libs/uci/root/sbin/luci-reload Executable file
View file

@ -0,0 +1,32 @@
#!/bin/sh
. /etc/functions.sh
apply_config() {
config_get init "$1" init
config_get exec "$1" exec
[ -n "$init" ] && reload_init "$2" "$init"
[ -n "$exec" ] && reload_exec "$2" "$exec"
}
reload_exec() {
[ -x $2 ] && {
echo "Reloading $1... "
$2 >/dev/null 2>&1 || echo "!!! Failed to reload $1 !!!"
}
}
reload_init() {
[ -x /etc/init.d/$2 ] && /etc/init.d/$2 enabled && {
echo "Reloading $1... "
/etc/init.d/$2 reload >/dev/null 2>&1 || echo "!!! Failed to reload $1 !!!"
}
}
config_load ucitrack
for i in $*
do
config_foreach apply_config $i $i
echo "done."
done

View file

@ -18,24 +18,6 @@ config extern flash_keep
option httpd "/etc/httpd.conf" option httpd "/etc/httpd.conf"
option firewall "/etc/firewall.user" option firewall "/etc/firewall.user"
config event uci_oncommit
option network "/sbin/luci-reload network firewall dnsmasq luci_splash"
option wireless "/sbin/luci-reload network firewall dnsmasq luci_splash"
option olsr "/sbin/luci-reload olsrd"
option dhcp "/sbin/luci-reload dnsmasq"
option dropbear "/sbin/luci-reload dropbear"
option httpd "/sbin/luci-reload httpd"
option fstab "/sbin/luci-reload fstab"
option qos "/sbin/luci-reload qos"
option system "/sbin/luci-reload led"
option firewall "/sbin/luci-reload firewall luci_splash"
option luci_hosts "/sbin/luci-reload luci_hosts dnsmasq"
option luci_ethers "/sbin/luci-reload luci_ethers dnsmasq"
option luci_splash "/sbin/luci-reload firewall luci_splash"
option upnpd "/etc/init.d/miniupnpd enabled && /sbin/luci-reload miniupnpd || /etc/init.d/miniupnpd stop"
option ntpclient "/sbin/luci-reload ntpclient"
option samba "/sbin/luci-reload samba"
config internal languages config internal languages
config internal sauth config internal sauth

View file

@ -182,7 +182,7 @@ end
function action_upgrade() function action_upgrade()
require("luci.model.uci") require("luci.model.uci")
local ret = nil local ret
local plat = luci.fs.mtime("/lib/upgrade/platform.sh") local plat = luci.fs.mtime("/lib/upgrade/platform.sh")
local tmpfile = "/tmp/firmware.img" local tmpfile = "/tmp/firmware.img"
local broadcom = os.execute('grep brcm_ /lib/upgrade/platform.sh >/dev/null 2>&1') == 0 local broadcom = os.execute('grep brcm_ /lib/upgrade/platform.sh >/dev/null 2>&1') == 0
@ -208,7 +208,9 @@ function action_upgrade()
local keepcfg = keep_avail and luci.http.formvalue("keepcfg") local keepcfg = keep_avail and luci.http.formvalue("keepcfg")
if plat and fname then if plat and fname then
ret = luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) ret = function()
return luci.sys.flash(tmpfile, keepcfg and _keep_pattern())
end
end end
luci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) luci.template.render("admin_system/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail})

View file

@ -24,27 +24,23 @@ function index()
end end
function convert_changes(changes) function convert_changes(changes)
local ret = {} local util = require "luci.util"
local ret
for r, tbl in pairs(changes) do for r, tbl in pairs(changes) do
for s, os in pairs(tbl) do for s, os in pairs(tbl) do
for o, v in pairs(os) do for o, v in pairs(os) do
local val, str ret = (ret and ret.."\n" or "") .. "%s%s.%s%s%s" % {
if (v == "") then v == "" and "-" or "",
str = "-" r,
val = "" s,
else o ~= ".type" and "."..o or "",
str = "" v ~= "" and "="..util.pcdata(v) or ""
val = "="..luci.util.pcdata(v) }
end
str = r.."."..s
if o ~= ".type" then
str = str.."."..o
end
table.insert(ret, str..val)
end end
end end
end end
return table.concat(ret, "\n") return ret
end end
function action_changes() function action_changes()
@ -54,52 +50,38 @@ end
function action_apply() function action_apply()
local path = luci.dispatcher.context.path local path = luci.dispatcher.context.path
local output = ""
local uci = luci.model.uci.cursor() local uci = luci.model.uci.cursor()
local changes = uci:changes() local changes = uci:changes()
local reload = {}
if changes then -- Collect files to be applied and commit changes
local com = {} for r, tbl in pairs(changes) do
local run = {} table.insert(reload, r)
if path[#path] ~= "apply" then
-- Collect files to be applied and commit changes uci:load(r)
for r, tbl in pairs(changes) do uci:commit(r)
if r then uci:unload(r)
if path[#path] ~= "apply" then
uci:load(r)
uci:commit(r)
uci:unload(r)
end
if luci.config.uci_oncommit and luci.config.uci_oncommit[r] then
run[luci.config.uci_oncommit[r]] = true
end
end
end
-- Search for post-commit commands
for cmd, i in pairs(run) do
output = output .. cmd .. ":\n" .. luci.util.exec(cmd) .. "\n"
end end
end end
local function _reload()
local cmd = uci:apply(reload, true)
return io.popen(cmd)
end
luci.template.render("admin_uci/apply", {changes=convert_changes(changes), output=output}) luci.template.render("admin_uci/apply", {changes=convert_changes(changes), reload=_reload})
end end
function action_revert() function action_revert()
local uci = luci.model.uci.cursor() local uci = luci.model.uci.cursor()
local changes = uci:changes() local changes = uci:changes()
if changes then
local revert = {}
-- Collect files to be reverted -- Collect files to be reverted
for r, tbl in pairs(changes) do for r, tbl in pairs(changes) do
uci:load(r) uci:load(r)
uci:revert(r) uci:revert(r)
uci:unload(r) uci:unload(r)
end
end end
luci.template.render("admin_uci/revert", {changes=convert_changes(changes)}) luci.template.render("admin_uci/revert", {changes=convert_changes(changes)})

View file

@ -34,7 +34,13 @@ $Id$
</div> </div>
</form> </form>
<% elseif ret then %> <% elseif ret then %>
<% if ret == 0 then %> <p><%:a_s_flash_received%></p>
<p><%:a_s_flash_inprogress%></p>
<!-- <%=string.rep(" ", 2048)%> -->
<% %>
<% local ret = ret()
if ret == 0 then %>
<div class="ok"><%:a_s_flash_flashed%></div> <div class="ok"><%:a_s_flash_flashed%></div>
<% else %> <% else %>
<div class="error"><%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)</div> <div class="error"><%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)</div>
@ -43,3 +49,4 @@ $Id$
<div class="error"><%:a_s_flash_notimplemented%></div> <div class="error"><%:a_s_flash_notimplemented%></div>
<% end %> <% end %>
<%+footer%> <%+footer%>
<% if ret == 0 then luci.sys.reboot() end %>

View file

@ -16,5 +16,14 @@ $Id$
<h1><%:config%></h1> <h1><%:config%></h1>
<p><%:uci_applied%>:</p> <p><%:uci_applied%>:</p>
<code><%=(changes or "-")%> <code><%=(changes or "-")%>
<%=output%></code>
<%
local fp = reload()
local line = fp:read()
while line do
write(line.."\n")
line = fp:read()
end
fp:close()
%></code>
<%+footer%> <%+footer%>

View file

@ -105,7 +105,9 @@ function action_upgrade()
local keepcfg = keep_avail and luci.http.formvalue("keepcfg") local keepcfg = keep_avail and luci.http.formvalue("keepcfg")
if plat and fname then if plat and fname then
ret = luci.sys.flash(tmpfile, keepcfg and _keep_pattern()) ret = function()
return luci.sys.flash(tmpfile, keepcfg and _keep_pattern())
end
end end
luci.template.render("mini/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail}) luci.template.render("mini/upgrade", {sysupgrade=plat, ret=ret, keep_avail=keep_avail})

View file

@ -20,31 +20,27 @@ function index()
entry({"mini", "uci"}, nil, i18n("config")) entry({"mini", "uci"}, nil, i18n("config"))
entry({"mini", "uci", "changes"}, call("action_changes"), i18n("changes"), 30) entry({"mini", "uci", "changes"}, call("action_changes"), i18n("changes"), 30)
entry({"mini", "uci", "revert"}, call("action_revert"), i18n("revert"), 20) entry({"mini", "uci", "revert"}, call("action_revert"), i18n("revert"), 20)
entry({"mini", "uci", "apply"}, call("action_apply"), i18n("saveapply"), 10) entry({"mini", "uci", "saveapply"}, call("action_apply"), i18n("saveapply"), 10)
end end
function convert_changes(changes) function convert_changes(changes)
local ret = {} local util = require "luci.util"
local ret
for r, tbl in pairs(changes) do for r, tbl in pairs(changes) do
for s, os in pairs(tbl) do for s, os in pairs(tbl) do
for o, v in pairs(os) do for o, v in pairs(os) do
local val, str ret = (ret and ret.."\n" or "") .. "%s%s.%s%s%s" % {
if (v == "") then v == "" and "-" or "",
str = "-" r,
val = "" s,
else o ~= ".type" and "."..o or "",
str = "" v ~= "" and "="..util.pcdata(v) or ""
val = "="..luci.util.pcdata(v) }
end
str = r.."."..s
if o ~= ".type" then
str = str.."."..o
end
table.insert(ret, str..val)
end end
end end
end end
return table.concat(ret, "\n") return ret
end end
function action_changes() function action_changes()
@ -53,49 +49,37 @@ function action_changes()
end end
function action_apply() function action_apply()
local path = luci.dispatcher.context.path
local uci = luci.model.uci.cursor() local uci = luci.model.uci.cursor()
local changes = uci:changes() local changes = uci:changes()
local output = "" local reload = {}
if changes then -- Collect files to be applied and commit changes
local com = {} for r, tbl in pairs(changes) do
local run = {} table.insert(reload, r)
uci:load(r)
-- Collect files to be applied and commit changes uci:commit(r)
for r, tbl in pairs(changes) do uci:unload(r)
if r then
uci:load(r)
uci:commit(r)
uci:unload(r)
if luci.config.uci_oncommit and luci.config.uci_oncommit[r] then
run[luci.config.uci_oncommit[r]] = true
end
end
end
-- Search for post-commit commands
for cmd, i in pairs(run) do
output = output .. cmd .. ":\n" .. luci.util.exec(cmd) .. "\n"
end
end end
local function _reload()
local cmd = uci:apply(reload, true)
return io.popen(cmd)
end
luci.template.render("mini/uci_apply", {changes=convert_changes(changes), output=output}) luci.template.render("mini/uci_apply", {changes=convert_changes(changes), reload=_reload})
end end
function action_revert() function action_revert()
local uci = luci.model.uci.cursor() local uci = luci.model.uci.cursor()
local changes = uci:changes() local changes = uci:changes()
if changes then
local revert = {}
-- Collect files to be reverted -- Collect files to be reverted
for r, tbl in pairs(changes) do for r, tbl in pairs(changes) do
uci:load(r) uci:load(r)
uci:revert(r) uci:revert(r)
uci:unload(r) uci:unload(r)
end
end end
luci.template.render("mini/uci_revert", {changes=convert_changes(changes)}) luci.template.render("mini/uci_revert", {changes=convert_changes(changes)})

View file

@ -16,5 +16,14 @@ $Id$
<h1><%:config%></h1> <h1><%:config%></h1>
<p><%:uci_applied%>:</p> <p><%:uci_applied%>:</p>
<code><%=(changes or "-")%> <code><%=(changes or "-")%>
<%=output%></code>
<%
local fp = reload()
local line = fp:read()
while line do
write(line.."\n")
line = fp:read()
end
fp:close()
%></code>
<%+footer%> <%+footer%>

View file

@ -34,7 +34,13 @@ $Id$
</div> </div>
</form> </form>
<% elseif ret then %> <% elseif ret then %>
<% if ret == 0 then %> <p><%:a_s_flash_received%></p>
<p><%:a_s_flash_inprogress%></p>
<!-- <%=string.rep(" ", 2048)%> -->
<% %>
<% local ret = ret()
if ret == 0 then %>
<div class="ok"><%:a_s_flash_flashed%></div> <div class="ok"><%:a_s_flash_flashed%></div>
<% else %> <% else %>
<div class="error"><%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)</div> <div class="error"><%:a_s_flash_flasherr%>! (<%:code%> <%=ret%>)</div>
@ -43,3 +49,4 @@ $Id$
<div class="error"><%:a_s_flash_notimplemented%></div> <div class="error"><%:a_s_flash_notimplemented%></div>
<% end %> <% end %>
<%+footer%> <%+footer%>
<% if ret == 0 then luci.sys.reboot() end %>