modules/admin-full: Fixes for rdate config
[project/luci.git] / modules / admin-full / luasrc / model / cbi / admin_system / system.lua
1 --[[
2 LuCI - Lua Configuration Interface
3
4 Copyright 2008 Steven Barth <steven@midlink.org>
5 Copyright 2011 Jo-Philipp Wich <xm@subsignal.org>
6
7 Licensed under the Apache License, Version 2.0 (the "License");
8 you may not use this file except in compliance with the License.
9 You may obtain a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 $Id$
14 ]]--
15
16 require("luci.sys")
17 require("luci.sys.zoneinfo")
18 require("luci.tools.webadmin")
19 require("luci.fs")
20 require("luci.config")
21
22 m = Map("system", translate("System"), translate("Here you can configure the basic aspects of your device like its hostname or the timezone."))
23 m:chain("luci")
24
25 local has_rdate = false
26
27 m.uci:foreach("system", "rdate",
28 function()
29 has_rdate = true
30 return false
31 end)
32
33
34 s = m:section(TypedSection, "system", translate("System Properties"))
35 s.anonymous = true
36 s.addremove = false
37
38 s:tab("general", translate("General Settings"))
39 s:tab("logging", translate("Logging"))
40 s:tab("language", translate("Language and Style"))
41
42
43 --
44 -- System Properties
45 --
46
47 local system, model, memtotal, memcached, membuffers, memfree = luci.sys.sysinfo()
48 local uptime = luci.sys.uptime()
49
50 s:taboption("general", DummyValue, "_system", translate("System")).value = system
51 s:taboption("general", DummyValue, "_cpu", translate("Processor")).value = model
52
53 s:taboption("general", DummyValue, "_kernel", translate("Kernel")).value =
54 luci.util.exec("uname -r") or "?"
55
56 local load1, load5, load15 = luci.sys.loadavg()
57 s:taboption("general", DummyValue, "_la", translate("Load")).value =
58 string.format("%.2f, %.2f, %.2f", load1, load5, load15)
59
60 s:taboption("general", DummyValue, "_memtotal", translate("Memory")).value =
61 string.format("%.2f MB (%.0f%% %s, %.0f%% %s, %.0f%% %s)",
62 tonumber(memtotal) / 1024,
63 100 * memcached / memtotal,
64 tostring(translate("cached")),
65 100 * membuffers / memtotal,
66 tostring(translate("buffered")),
67 100 * memfree / memtotal,
68 tostring(translate("free"))
69 )
70
71 s:taboption("general", DummyValue, "_systime", translate("Local Time")).value =
72 os.date("%c")
73
74 s:taboption("general", DummyValue, "_uptime", translate("Uptime")).value =
75 luci.tools.webadmin.date_format(tonumber(uptime))
76
77 hn = s:taboption("general", Value, "hostname", translate("Hostname"))
78 hn.datatype = "hostname"
79 function hn.write(self, section, value)
80 Value.write(self, section, value)
81 luci.sys.hostname(value)
82 end
83
84
85 tz = s:taboption("general", ListValue, "zonename", translate("Timezone"))
86 tz:value("UTC")
87
88 for i, zone in ipairs(luci.sys.zoneinfo.TZ) do
89 tz:value(zone[1])
90 end
91
92 function tz.write(self, section, value)
93 local function lookup_zone(title)
94 for _, zone in ipairs(luci.sys.zoneinfo.TZ) do
95 if zone[1] == title then return zone[2] end
96 end
97 end
98
99 AbstractValue.write(self, section, value)
100 local timezone = lookup_zone(value) or "GMT0"
101 self.map.uci:set("system", section, "timezone", timezone)
102 luci.fs.writefile("/etc/TZ", timezone .. "\n")
103 end
104
105
106 --
107 -- Logging
108 --
109
110 o = s:taboption("logging", Value, "log_size", translate("System log buffer size"), "kiB")
111 o.optional = true
112 o.placeholder = 16
113 o.datatype = "uinteger"
114
115 o = s:taboption("logging", Value, "log_ip", translate("External system log server"))
116 o.optional = true
117 o.placeholder = "0.0.0.0"
118 o.datatype = "ip4addr"
119
120 o = s:taboption("logging", Value, "log_port", translate("External system log server port"))
121 o.optional = true
122 o.placeholder = 514
123 o.datatype = "port"
124
125 o = s:taboption("logging", ListValue, "conloglevel", translate("Log output level"))
126 o:value(7, translate("Debug"))
127 o:value(6, translate("Info"))
128 o:value(5, translate("Notice"))
129 o:value(4, translate("Warning"))
130 o:value(3, translate("Error"))
131 o:value(2, translate("Critical"))
132 o:value(1, translate("Alert"))
133 o:value(0, translate("Emergency"))
134
135 o = s:taboption("logging", ListValue, "cronloglevel", translate("Cron Log Level"))
136 o.default = 8
137 o:value(5, translate("Debug"))
138 o:value(8, translate("Normal"))
139 o:value(9, translate("Warning"))
140
141
142 --
143 -- Langauge & Style
144 --
145
146 o = s:taboption("language", ListValue, "_lang", translate("Language"))
147 o:value("auto")
148
149 local i18ndir = luci.i18n.i18ndir .. "base."
150 for k, v in luci.util.kspairs(luci.config.languages) do
151 local file = i18ndir .. k:gsub("_", "-")
152 if k:sub(1, 1) ~= "." and luci.fs.access(file .. ".lmo") then
153 o:value(k, v)
154 end
155 end
156
157 function o.cfgvalue(...)
158 return m.uci:get("luci", "main", "lang")
159 end
160
161 function o.write(self, section, value)
162 m.uci:set("luci", "main", "lang", value)
163 end
164
165
166 o = s:taboption("language", ListValue, "_mediaurlbase", translate("Design"))
167 for k, v in pairs(luci.config.themes) do
168 if k:sub(1, 1) ~= "." then
169 o:value(v, k)
170 end
171 end
172
173 function o.cfgvalue(...)
174 return m.uci:get("luci", "main", "mediaurlbase")
175 end
176
177 function o.write(self, section, value)
178 m.uci:set("luci", "main", "mediaurlbase", value)
179 end
180
181
182 --
183 -- Rdate
184 --
185
186 if has_rdate then
187 m3= Map("timeserver", translate("Time Server (rdate)"))
188 s = m3:section(TypedSection, "timeserver")
189 s.anonymous = true
190 s.addremove = true
191 s.template = "cbi/tblsection"
192
193 h = s:option(Value, "hostname", translate("Name"))
194 h.rmempty = true
195 h.datatype = host
196 i = s:option(ListValue, "interface", translate("Interface"))
197 i.rmempty = true
198 i:value("", translate("Default"))
199 m3.uci:foreach("network", "interface",
200 function (section)
201 local ifc = section[".name"]
202 if ifc ~= "loopback" then
203 i:value(ifc)
204 end
205 end
206 )
207 end
208
209
210 m2 = Map("luci")
211
212 f = m2:section(NamedSection, "main", "core", translate("Files to be kept when flashing a new firmware"))
213
214 f:tab("detected", translate("Detected Files"),
215 translate("The following files are detected by the system and will be kept automatically during sysupgrade"))
216
217 f:tab("custom", translate("Custom Files"),
218 translate("This is a list of shell glob patterns for matching files and directories to include during sysupgrade"))
219
220 d = f:taboption("detected", DummyValue, "_detected", translate("Detected files"))
221 d.rawhtml = true
222 d.cfgvalue = function(s)
223 local list = io.popen(
224 "( find $(sed -ne '/^[[:space:]]*$/d; /^#/d; p' /etc/sysupgrade.conf " ..
225 "/lib/upgrade/keep.d/* 2>/dev/null) -type f 2>/dev/null; " ..
226 "opkg list-changed-conffiles ) | sort -u"
227 )
228
229 if list then
230 local files = { "<ul>" }
231
232 while true do
233 local ln = list:read("*l")
234 if not ln then
235 break
236 else
237 files[#files+1] = "<li>"
238 files[#files+1] = luci.util.pcdata(ln)
239 files[#files+1] = "</li>"
240 end
241 end
242
243 list:close()
244 files[#files+1] = "</ul>"
245
246 return table.concat(files, "")
247 end
248
249 return "<em>" .. translate("No files found") .. "</em>"
250 end
251
252 c = f:taboption("custom", TextValue, "_custom", translate("Custom files"))
253 c.rmempty = false
254 c.cols = 70
255 c.rows = 30
256
257 c.cfgvalue = function(self, section)
258 return nixio.fs.readfile("/etc/sysupgrade.conf")
259 end
260
261 c.write = function(self, section, value)
262 value = value:gsub("\r\n?", "\n")
263 return nixio.fs.writefile("/etc/sysupgrade.conf", value)
264 end
265
266
267 return m, m3, m2