NIU: More pages

This commit is contained in:
Steven Barth 2009-11-10 16:02:48 +00:00
parent 4c08e29387
commit 7aed1e4b9d
14 changed files with 435 additions and 51 deletions

View file

@ -12,6 +12,9 @@ uci_model.cursor_state = function()
return uci_core.cursor(SYSROOT .. "/etc/config", SYSROOT .. "/var/state")
end
uci_model.inst = uci_model.cursor()
uci_model.inst_state = uci_model.cursor_state()
-- override uvl access
local uvl_model = require "luci.uvl"
local uvl_init = uvl_model.UVL.__init__

View file

@ -222,6 +222,12 @@ function Node.__init__(self, title, description)
end
-- hook helper
function Node._run_hook(self, hook)
if type(self[hook]) == "function" then
return self[hook](self)
end
end
function Node._run_hooks(self, ...)
local f
local r = false
@ -528,9 +534,9 @@ function Delegator.add(self, name, node)
end
function Delegator.insert_after(self, name, after)
local n = #self.chain
local n = #self.chain + 1
for k, v in ipairs(self.chain) do
if v == state then
if v == after then
n = k + 1
break
end
@ -599,8 +605,7 @@ function Delegator.parse(self, ...)
return FORM_NODATA
elseif stat > FORM_PROCEED
and (not newcurrent or not self:get(newcurrent)) then
self:_run_hooks("on_done")
return FORM_DONE
return self:_run_hook("on_done") or FORM_DONE
else
self.current = newcurrent or self.current
self.active = self:get(self.current)

View file

@ -58,7 +58,10 @@ function cursor_state()
end
local Cursor = getmetatable(cursor())
inst = cursor()
inst_state = cursor_state()
local Cursor = getmetatable(inst)
--- Applies UCI configuration changes
-- @param configlist List of UCI configurations

View file

@ -34,6 +34,7 @@ local nixio = require "nixio", require "nixio.util"
module("luci.dispatcher", package.seeall)
context = util.threadlocal()
uci = require "luci.model.uci"
authenticator = {}

View file

@ -36,8 +36,6 @@ function dashboard()
local tpl = require "luci.template"
local utl = require "luci.util"
local uci = require "luci.model.uci"
local str = require "luci.store"
str.uci_state = str.uci_state or uci.cursor()
local nds = dsp.node("niu").nodes
tpl.render("niu/dashboard", {utl = utl, nodes = nds, dsp = dsp, tpl = tpl})

View file

@ -16,17 +16,21 @@ local req = require
module "luci.controller.niu.network"
function index()
entry({"niu", "network"}, nil, "Network").dbtemplate = "niu/network"
entry({"niu", "network", "lan"},
cbi("niu/network/lan", {on_success_to={"niu"}}), "Configure LAN", 10)
entry({"niu", "network"}, nil, "Network", 10).dbtemplate = "niu/network"
entry({"niu", "network", "wan"},
cbi("niu/network/wan", {on_success_to={"niu"}}), "Configure Internet", 20)
cbi("niu/network/wan", {on_success_to={"niu"}}), "Configure Internet Connection", 10)
entry({"niu", "network", "lan"},
cbi("niu/network/lan", {on_success_to={"niu"}}), "Configure Local Network", 20)
entry({"niu", "network", "assign"}, cbi("niu/network/assign",
{on_success_to={"niu"}}), "Address Assignment", 30)
uci.inst_state:foreach("dhcp", "dhcp", function(s)
if s.interface == "lan" and s.ignore ~= "1" then
entry({"niu", "network", "assign"}, cbi("niu/network/assign",
{on_success_to={"niu"}}), "Assign local addresses", 30)
end
end)
entry({"niu", "network", "routes"}, cbi("niu/network/routes",
{on_success_to={"niu"}}), "Custom Routing", 40)
{on_success_to={"niu"}}), "Assign custom routes", 40)
end

View file

@ -12,56 +12,249 @@ You may obtain a copy of the License at
$Id$
]]--
local require, pairs, unpack = require, pairs, unpack
local require, pairs, unpack, tonumber = require, pairs, unpack, tonumber
module "luci.controller.niu.system"
function index()
entry({"niu", "system"}, nil, "System").dbtemplate = "niu/system"
entry({"niu", "system"}, nil, "System", 20).dbtemplate = "niu/system"
entry({"niu", "system", "general"},
cbi("niu/system/general", {on_success_to={"niu"}}), "General", 10)
cbi("niu/system/general", {on_success_to={"niu"}}), "Configure Device", 10)
entry({"niu", "system", "backup"}, call("backup"), "Backup Settings", 20)
entry({"niu", "system", "backup"}, call("backup"), "Backup or Restore Settings", 20)
entry({"niu", "system", "upgrade"}, call("upgrade"), "Upgrade Firmware", 40)
end
function backup()
local os = require "os"
local uci = require "luci.model.uci".cursor()
local dsp = require "luci.dispatcher"
local os, io = require "os", require "io"
local uci = require "luci.model.uci".inst
local nixio, nutl = require "nixio", require "nixio.util"
local fs = require "nixio.fs"
local http = require "luci.http"
local tpl = require "luci.template"
local call = {"/bin/tar", "-cz"}
for k, v in pairs(uci:get_all("luci", "flash_keep")) do
if k:byte() ~= 46 then -- k[1] ~= "."
nutl.consume(fs.glob(v), call)
local restore_fpi
http.setfilehandler(
function(meta, chunk, eof)
if not restore_fpi then
restore_fpi = io.popen("tar -xzC/ >/dev/null 2>&1", "w")
end
if chunk then
restore_fpi:write(chunk)
end
if eof then
restore_fpi:close()
end
end
end
http.header(
'Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % {
nixio.uname().nodename, os.date("%Y-%m-%d")
}
)
http.prepare_content("application/x-targz")
local reset_avail = (fs.readfile("/proc/mtd") or ""):find('"rootfs_data"')
local upload = http.formvalue("archive")
local backup = http.formvalue("backup")
local reset = reset_avail and http.formvalue("reset")
local backup_cmd = "tar -cz %s 2>/dev/null"
local fdin, fdout = nixio.pipe()
local devnull = nixio.open("/dev/null", "r+")
local proc = nixio.fork()
if proc == 0 then
fdin:close()
nixio.dup(devnull, nixio.stdin)
nixio.dup(devnull, nixio.stderr)
nixio.dup(fdout, nixio.stdout)
nixio.exec(unpack(call))
os.exit(1)
if http.formvalue("cancel") then
return http.redirect(dsp.build_url("niu"))
end
fdout:close()
http.splice(fdin)
http.close()
if backup then
local call = {"/bin/tar", "-cz"}
for k, v in pairs(uci:get_all("luci", "flash_keep")) do
if k:byte() ~= 46 then -- k[1] ~= "."
nutl.consume(fs.glob(v), call)
end
end
http.header(
'Content-Disposition', 'attachment; filename="backup-%s-%s.tar.gz"' % {
nixio.uname().nodename, os.date("%Y-%m-%d")
}
)
http.prepare_content("application/x-targz")
local fdin, fdout = nixio.pipe()
local devnull = nixio.open("/dev/null", "r+")
local proc = nixio.fork()
if proc == 0 then
fdin:close()
nixio.dup(devnull, nixio.stdin)
nixio.dup(devnull, nixio.stderr)
nixio.dup(fdout, nixio.stdout)
nixio.exec(unpack(call))
os.exit(1)
end
fdout:close()
http.splice(fdin)
http.close()
elseif (upload and #upload > 0) or reset then
tpl.render("niu/system/reboot")
if nixio.fork() == 0 then
nixio.nanosleep(1)
if reset then
nixio.execp("mtd", "-r", "erase", "rootfs_data")
else
nixio.execp("reboot")
end
os.exit(1)
end
else
tpl.render("niu/system/backup", {reset_avail = reset_avail})
end
end
function upgrade()
local io, os, table = require "io", require "os", require "table"
local uci = require "luci.store".uci_state
local http = require "luci.http"
local util = require "luci.util"
local tpl = require "luci.template"
local nixio = require "nixio", require "nixio.util", require "nixio.fs"
local tmpfile = "/tmp/firmware.img"
local function image_supported()
-- XXX: yay...
return ( 0 == os.execute(
". /etc/functions.sh; " ..
"include /lib/upgrade; " ..
"platform_check_image %q >/dev/null"
% tmpfile
) )
end
local function image_checksum()
return (util.exec("md5sum %q" % tmpfile):match("^([^%s]+)"))
end
local function storage_size()
local size = 0
if nixio.fs.access("/proc/mtd") then
for l in io.lines("/proc/mtd") do
local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
if n == "linux" then
size = tonumber(s, 16)
break
end
end
elseif nixio.fs.access("/proc/partitions") then
for l in io.lines("/proc/partitions") do
local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
if b and n and not n:match('[0-9]') then
size = tonumber(b) * 1024
break
end
end
end
return size
end
-- Install upload handler
local file
http.setfilehandler(
function(meta, chunk, eof)
if not nixio.fs.access(tmpfile) and not file and chunk and #chunk > 0 then
file = io.open(tmpfile, "w")
end
if file and chunk then
file:write(chunk)
end
if file and eof then
file:close()
end
end
)
-- Determine state
local keep_avail = true
local step = tonumber(http.formvalue("step") or 1)
local has_image = nixio.fs.access(tmpfile)
local has_support = image_supported()
local has_platform = nixio.fs.access("/lib/upgrade/platform.sh")
local has_upload = http.formvalue("image")
-- This does the actual flashing which is invoked inside an iframe
-- so don't produce meaningful errors here because the the
-- previous pages should arrange the stuff as required.
if step == 4 then
if has_platform and has_image and has_support then
-- Mimetype text/plain
http.prepare_content("text/plain")
local call = {}
for k, v in pairs(uci:get_all("luci", "flash_keep")) do
if k:byte() ~= 46 then -- k[1] ~= "."
nixio.util.consume(nixio.fs.glob(v), call)
end
end
-- Now invoke sysupgrade
local keepcfg = keep_avail and http.formvalue("keepcfg") == "1"
local fd = io.popen("/sbin/luci-flash %s %q" %{
keepcfg and "-k %q" % table.concat(call, " ") or "", tmpfile
})
if fd then
while true do
local ln = fd:read("*l")
if not ln then break end
http.write(ln .. "\n")
end
fd:close()
end
-- Make sure the device is rebooted
if nixio.fork() == 0 then
nixio.nanosleep(1)
nixio.execp("reboot")
os.exit(1)
end
end
--
-- This is step 1-3, which does the user interaction and
-- image upload.
--
-- Step 1: file upload, error on unsupported image format
elseif not has_image or not has_support or step == 1 then
-- If there is an image but user has requested step 1
-- or type is not supported, then remove it.
if has_image then
nixio.fs.unlink(tmpfile)
end
tpl.render("niu/system/upgrade", {
step=1,
bad_image=(has_image and not has_support or false),
keepavail=keep_avail,
supported=has_platform
} )
-- Step 2: present uploaded file, show checksum, confirmation
elseif step == 2 then
tpl.render("niu/system/upgrade", {
step=2,
checksum=image_checksum(),
filesize=nixio.fs.stat(tmpfile).size,
flashsize=storage_size(),
keepconfig=(keep_avail and http.formvalue("keepcfg") == "1")
} )
-- Step 3: load iframe which calls the actual flash procedure
elseif step == 3 then
tpl.render("niu/system/upgrade", {
step=3,
keepconfig=(keep_avail and http.formvalue("keepcfg") == "1")
} )
end
end

View file

@ -1,10 +1,12 @@
local cursor = require "luci.model.uci".cursor()
local uci = require "luci.model.uci"
local cursor = uci.cursor()
local d = Delegator()
d.allow_finish = true
d.allow_back = true
d.allow_cancel = true
d:add("lan1", load("niu/network/lan1"))
d:set("warnip", {Template("niu/network/warn_ip_change")})
function d.on_cancel()
cursor:revert("network")
@ -12,6 +14,12 @@ function d.on_cancel()
end
function d.on_done()
if uci.inst_state:get("network", "lan", "ipaddr") ~= cursor:get("network", "lan", "ipaddr") then
local cs = uci.cursor_state()
cs:set("network", "lan", "_ipchanged", "1")
cs:save("network")
end
cursor:commit("network")
cursor:commit("dhcp")
end

View file

@ -0,0 +1 @@
local f = Form("reboot", "Rebooting Device", "Device is rebooting. Please wait...")

View file

@ -1,13 +1,19 @@
<%
local dsp = require "luci.dispatcher"
local utl = require "luci.util"
local str = require "luci.store"
local uci = require "luci.model.uci"
local nws = {}
str.uci_state:foreach("network", "interface", function(s)
uci.inst_state:foreach("network", "interface", function(s)
nws[#nws+1] = s
end)
if uci.inst_state:get("network", "lan", "_ipchanged") and
uci.inst_state:revert("network", "lan", "_ipchanged") then
include("niu/network/warn_ip_change")
end
%>
<div>Status:</div>
<table>
<%

View file

@ -0,0 +1,2 @@
<strong>Warning!<br />
Device IP has changed.</strong>

View file

@ -0,0 +1,41 @@
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<h3><%:Backup / Restore%></h3>
<p><%:Here you can backup and restore your router configuration and - if possible - reset the router to the default settings.%></p>
<br />
<div>
<ul>
<li><a href="<%=REQUEST_URI%>?backup=kthxbye"><%:Create backup%></a></li>
<% if reset_avail then -%>
<li><a href="<%=REQUEST_URI%>?reset=yarly" onclick="return confirm('<%:Proceed reverting all settings and resetting to firmware defaults?%>')"><%:Reset router to defaults%></a></li>
<% end -%>
</ul>
</div>
<br />
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
<div class="left"><%:Backup Archive%>:</div>
<div>
<input type="file" size="30" name="archive" />
</div>
<div>
<input type="submit" name="cancel" class="cbi-input-cancel" value="<%:Cancel%>" />
<input type="submit" class="cbi-input-apply" value="<%:Restore backup%>" />
</div>
</form>
<%+footer%>

View file

@ -0,0 +1,14 @@
Rebooting. Please wait...
<script type="text/javascript">
window.setInterval(function() {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET', '/', true);
xmlHttp.onreadystatechange = function () {
if (xmlHttp.readyState == 4 && req.status >= 200 && req.status < 400) {
window.location = "/";
}
};
xmlHttp.send(null);
}, 10000);
</script>

View file

@ -0,0 +1,105 @@
<%#
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008-2009 Jo-Philipp Wich <xm@subsignal.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
$Id$
-%>
<%+header%>
<h2><a id="content" name="content"><%:System%></a></h2>
<h3><%:Flash Firmware%></h3>
<% if step == 1 then %>
<% if supported then %>
<form method="post" action="<%=REQUEST_URI%>" enctype="multipart/form-data">
<p>
<%:Upload an OpenWrt image file to reflash the device.%>
<% if bad_image then %>
<br /><br />
<div class="error"><%:The uploaded image file does not
contain a supported format. Make sure that you choose the generic
image format for your platform. %></div>
<% end %>
</p>
<div>
<%:Firmware image%>:<br />
<input type="hidden" name="step" value="2" />
<input type="file" size="30" name="image" />
<br />
<br />
<% if keepavail then -%>
<input type="checkbox" name="keepcfg" value="1" checked="checked" />
<span class="bold"><%:Keep configuration files%></span>
<% end -%>
<br />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Upload image%>" />
</div>
</form>
<% else %>
<div class="error"><%_ Sorry.
OpenWrt does not support a system upgrade on this platform.<br />
You need to manually flash your device. %></div>
<% end %>
<% elseif step == 2 then %>
<p>
<%_ The flash image was uploaded.
Below is the checksum and file size listed,
compare them with the original file to ensure data integrity.<br />
Click "Proceed" below to start the flash procedure. %>
<% if flashsize > 0 and filesize > flashsize then %>
<br /><br />
<div class="error"><%:It appears that you try to
flash an image that does not fit into the flash memory, please verify
the image file! %></div>
<% end %>
<br />
<ul>
<li><%:Checksum%>: <code><%=checksum%></code></li>
<li><%:Size%>: <%
local w = require "luci.tools.webadmin"
write(w.byte_format(filesize))
if flashsize > 0 then
write(luci.i18n.translatef(
" (%s available)",
w.byte_format(flashsize)
))
end
%></li>
</ul>
</p>
<div class="cbi-page-actions right">
<form style="display:inline">
<input type="hidden" name="step" value="3" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input class="cbi-button cbi-button-apply" type="submit" value="<%:Proceed%>" />
</form>
<form style="display:inline">
<input type="hidden" name="step" value="1" />
<input type="hidden" name="keepcfg" value="<%=keepconfig and "1" or "0"%>" />
<input class="cbi-button cbi-button-reset" type="submit" value="<%:Cancel%>" />
</form>
</div>
<% elseif step == 3 then %>
<p><%_ The system is flashing now.<br />
DO NOT POWER OFF THE DEVICE!<br />
Wait a few minutes until you try to reconnect.
It might be necessary to renew the address of your computer to reach the device
again, depending on your settings. %></p>
<iframe src="<%=REQUEST_URI%>?step=4&#38;keepcfg=<%=keepconfig and "1" or "0"%>" style="border:1px solid black; width:100%; height:150px"></iframe>
<% end %>
<%+footer%>