03155dbb62247d26272024fb9f66c3ddd1a63f1a
[oweals/luci.git] / modules / luci-mod-admin-full / luasrc / view / admin_status / index.htm
1 <%#
2  Copyright 2008 Steven Barth <steven@midlink.org>
3  Copyright 2008-2011 Jo-Philipp Wich <jow@openwrt.org>
4  Licensed to the public under the Apache License 2.0.
5 -%>
6
7 <%
8         local fs = require "nixio.fs"
9         local ipc = require "luci.ip"
10         local util = require "luci.util"
11         local stat = require "luci.tools.status"
12         local ver = require "luci.version"
13
14         local has_ipv6 = fs.access("/proc/net/ipv6_route")
15         local has_dhcp = fs.access("/etc/config/dhcp")
16         local has_wifi = ((fs.stat("/etc/config/wireless", "size") or 0) > 0)
17
18         local sysinfo = luci.util.ubus("system", "info") or { }
19         local boardinfo = luci.util.ubus("system", "board") or { }
20         local unameinfo = nixio.uname() or { }
21
22         local meminfo = sysinfo.memory or {
23                 total = 0,
24                 free = 0,
25                 buffered = 0,
26                 shared = 0
27         }
28
29         local swapinfo = sysinfo.swap or {
30                 total = 0,
31                 free = 0
32         }
33
34         local has_dsl = fs.access("/etc/init.d/dsl_control")
35
36         if luci.http.formvalue("status") == "1" then
37                 local ntm = require "luci.model.network".init()
38                 local wan = ntm:get_wannet()
39                 local wan6 = ntm:get_wan6net()
40
41                 local conn_count = tonumber(
42                         fs.readfile("/proc/sys/net/netfilter/nf_conntrack_count") or "") or 0
43
44                 local conn_max = tonumber(luci.sys.exec(
45                         "sysctl -n -e net.nf_conntrack_max net.ipv4.netfilter.ip_conntrack_max"
46                 ):match("%d+")) or 4096
47
48                 local rv = {
49                         uptime     = sysinfo.uptime or 0,
50                         localtime  = os.date(),
51                         loadavg    = sysinfo.load or { 0, 0, 0 },
52                         memory     = meminfo,
53                         swap       = swapinfo,
54                         connmax    = conn_max,
55                         conncount  = conn_count,
56                         wifinets   = stat.wifi_networks()
57                 }
58
59                 if wan then
60                         local dev = wan:get_interface()
61                         local link = dev and ipc.link(dev:name())
62                         rv.wan = {
63                                 ipaddr  = wan:ipaddr(),
64                                 gwaddr  = wan:gwaddr(),
65                                 netmask = wan:netmask(),
66                                 dns     = wan:dnsaddrs(),
67                                 expires = wan:expires(),
68                                 uptime  = wan:uptime(),
69                                 proto   = wan:proto(),
70                                 i18n    = wan:get_i18n(),
71                                 ifname  = wan:ifname(),
72                                 link    = wan:adminlink(),
73                                 mac     = dev and dev:mac(),
74                                 type    = dev and dev:type(),
75                                 name    = dev and dev:get_i18n(),
76                                 ether   = link and link.type == 1
77                         }
78                 end
79
80                 if wan6 then
81                         local dev = wan6:get_interface()
82                         local link = dev and ipc.link(dev:name())
83                         rv.wan6 = {
84                                 ip6addr   = wan6:ip6addr(),
85                                 gw6addr   = wan6:gw6addr(),
86                                 dns       = wan6:dns6addrs(),
87                                 ip6prefix = wan6:ip6prefix(),
88                                 uptime    = wan6:uptime(),
89                                 proto     = wan6:proto(),
90                                 i18n      = wan6:get_i18n(),
91                                 ifname    = wan6:ifname(),
92                                 link      = wan6:adminlink(),
93                                 mac       = dev and dev:mac(),
94                                 type      = dev and dev:type(),
95                                 name      = dev and dev:get_i18n(),
96                                 ether     = link and link.type == 1
97                         }
98                 end
99
100                 if has_dsl then
101                         local dsl_stat = luci.sys.exec("/etc/init.d/dsl_control lucistat")
102                         local dsl_func = loadstring(dsl_stat)
103                         if dsl_func then
104                                 rv.dsl = dsl_func()
105                         end
106                 end
107
108                 luci.http.prepare_content("application/json")
109                 luci.http.write_json(rv)
110
111                 return
112         end
113 -%>
114
115 <%+header%>
116
117 <script type="text/javascript">//<![CDATA[
118         function progressbar(v, m)
119         {
120                 var vn = parseInt(v) || 0;
121                 var mn = parseInt(m) || 100;
122                 var pc = Math.floor((100 / mn) * vn);
123
124                 return String.format(
125                         '<div style="width:100%%; max-width:200px; position:relative; border:1px solid #999999">' +
126                                 '<div style="background-color:#CCCCCC; width:%d%%; height:15px">' +
127                                         '<div style="position:absolute; left:0; top:0; text-align:center; width:100%%; color:#000000">' +
128                                                 '<small>%s / %s (%d%%)</small>' +
129                                         '</div>' +
130                                 '</div>' +
131                         '</div>', pc, v, m, pc
132                 );
133         }
134
135         function labelList(items, offset) {
136                 var rv = [ ];
137
138                 for (var i = offset || 0; i < items.length; i += 2) {
139                         var label = items[i],
140                             value = items[i+1];
141
142                         if (value === undefined || value === null)
143                                 continue;
144
145                         if (label)
146                                 rv.push(E('strong', [label, ': ']));
147
148                         rv.push(value, E('br'));
149                 }
150
151                 return rv;
152         }
153
154         function renderBox(title, active, childs) {
155                 childs = childs || [];
156                 childs.unshift(E('span', labelList(arguments, 3)));
157
158                 return E('div', { class: 'ifacebox' }, [
159                         E('div', { class: 'ifacebox-head center ' + (active ? 'active' : '') },
160                                 E('strong', title)),
161                         E('div', { class: 'ifacebox-body left' }, childs)
162                 ]);
163         }
164
165         function renderBadge(icon, title) {
166                 return E('span', { class: 'ifacebadge' }, [
167                         E('img', { src: icon, title: title || '' }),
168                         E('span', labelList(arguments, 2))
169                 ]);
170         }
171
172         XHR.poll(5, '<%=REQUEST_URI%>', { status: 1 },
173                 function(x, info)
174                 {
175                         var us = document.getElementById('upstream_status_table');
176
177                         while (us.lastElementChild)
178                                 us.removeChild(us.lastElementChild);
179
180                         var ifc = info.wan || {};
181
182                         us.appendChild(renderBox(
183                                 '<%:IPv4 Upstream%>',
184                                 (ifc.ifname && ifc.proto != 'none'),
185                                 [ E('div', {}, renderBadge(
186                                         '<%=resource%>/icons/%s.png'.format((ifc && ifc.type) ? ifc.type : 'ethernet_disabled'), null,
187                                         '<%:Device%>', ifc ? (ifc.name || ifc.ifname || '-') : '-',
188                                         '<%:MAC-Address%>', (ifc && ifc.ether) ? ifc.mac : null)) ],
189                                 '<%:Protocol%>', ifc.i18n || E('em', '<%:Not connected%>'),
190                                 '<%:Address%>', (ifc.ipaddr) ? ifc.ipaddr : '0.0.0.0',
191                                 '<%:Netmask%>', (ifc.netmask && ifc.netmask != ifc.ipaddr) ? ifc.netmask : '255.255.255.255',
192                                 '<%:Gateway%>', (ifc.gwaddr) ? ifc.gwaddr : '0.0.0.0',
193                                 '<%:DNS%> 1', (ifc.dns) ? ifc.dns[0] : null,
194                                 '<%:DNS%> 2', (ifc.dns) ? ifc.dns[1] : null,
195                                 '<%:DNS%> 3', (ifc.dns) ? ifc.dns[2] : null,
196                                 '<%:DNS%> 4', (ifc.dns) ? ifc.dns[3] : null,
197                                 '<%:DNS%> 5', (ifc.dns) ? ifc.dns[4] : null,
198                                 '<%:Expires%>', (ifc.expires > -1) ? '%t'.format(ifc.expires) : null,
199                                 '<%:Connected%>', (ifc.uptime > 0) ? '%t'.format(ifc.uptime) : null));
200
201                         <% if has_ipv6 then %>
202                         var ifc6 = info.wan6 || {};
203
204                         us.appendChild(renderBox(
205                                 '<%:IPv6 Upstream%>',
206                                 (ifc6.ifname && ifc6.proto != 'none'),
207                                 [ E('div', {}, renderBadge(
208                                         '<%=resource%>/icons/%s.png'.format(ifc6.type || 'ethernet_disabled'), null,
209                                         '<%:Device%>', ifc6 ? (ifc6.name || ifc6.ifname || '-') : '-',
210                                         '<%:MAC-Address%>', (ifc6 && ifc6.ether) ? ifc6.mac : null)) ],
211                                 '<%:Protocol%>', ifc6.i18n ? (ifc6.i18n + (ifc6.proto === 'dhcp' && ifc6.ip6prefix ? '-PD' : '')) : E('em', '<%:Not connected%>'),
212                                 '<%:Prefix Delegated%>', ifc6.ip6prefix,
213                                 '<%:Address%>', (ifc6.ip6prefix) ? (ifc6.ip6addr || null) : (ifc6.ipaddr || '::'),
214                                 '<%:Gateway%>', (ifc6.gw6addr) ? ifc6.gw6addr : '::',
215                                 '<%:DNS%> 1', (ifc6.dns) ? ifc6.dns[0] : null,
216                                 '<%:DNS%> 2', (ifc6.dns) ? ifc6.dns[1] : null,
217                                 '<%:DNS%> 3', (ifc6.dns) ? ifc6.dns[2] : null,
218                                 '<%:DNS%> 4', (ifc6.dns) ? ifc6.dns[3] : null,
219                                 '<%:DNS%> 5', (ifc6.dns) ? ifc6.dns[4] : null,
220                                 '<%:Connected%>', (ifc6.uptime > 0) ? '%t'.format(ifc6.uptime) : null));
221                         <% end %>
222
223                         <% if has_dsl then %>
224                                 var dsl_i = document.getElementById('dsl_i');
225                                 var dsl_s = document.getElementById('dsl_s');
226
227                                 var s = String.format(
228                                         '<strong><%:Status%>: </strong>%s<br />' +
229                                         '<strong><%:Line State%>: </strong>%s [0x%x]<br />' +
230                                         '<strong><%:Line Mode%>: </strong>%s<br />' +
231                                         '<strong><%:Annex%>: </strong>%s<br />' +
232                                         '<strong><%:Profile%>: </strong>%s<br />' +
233                                         '<strong><%:Data Rate%>: </strong>%s/s / %s/s<br />' +
234                                         '<strong><%:Max. Attainable Data Rate (ATTNDR)%>: </strong>%s/s / %s/s<br />' +
235                                         '<strong><%:Latency%>: </strong>%s / %s<br />' +
236                                         '<strong><%:Line Attenuation (LATN)%>: </strong>%s dB / %s dB<br />' +
237                                         '<strong><%:Signal Attenuation (SATN)%>: </strong>%s dB / %s dB<br />' +
238                                         '<strong><%:Noise Margin (SNR)%>: </strong>%s dB / %s dB<br />' +
239                                         '<strong><%:Aggregate Transmit Power(ACTATP)%>: </strong>%s dB / %s dB<br />' +
240                                         '<strong><%:Forward Error Correction Seconds (FECS)%>: </strong>%s / %s<br />' +
241                                         '<strong><%:Errored seconds (ES)%>: </strong>%s / %s<br />' +
242                                         '<strong><%:Severely Errored Seconds (SES)%>: </strong>%s / %s<br />' +
243                                         '<strong><%:Loss of Signal Seconds (LOSS)%>: </strong>%s / %s<br />' +
244                                         '<strong><%:Unavailable Seconds (UAS)%>: </strong>%s / %s<br />' +
245                                         '<strong><%:Header Error Code Errors (HEC)%>: </strong>%s / %s<br />' +
246                                         '<strong><%:Non Pre-emtive CRC errors (CRC_P)%>: </strong>%s / %s<br />' +
247                                         '<strong><%:Pre-emtive CRC errors (CRCP_P)%>: </strong>%s / %s<br />' +
248                                         '<strong><%:Line Uptime%>: </strong>%s<br />' +
249                                         '<strong><%:ATU-C System Vendor ID%>: </strong>%s<br />' +
250                                         '<strong><%:Power Management Mode%>: </strong>%s<br />',
251                                                 info.dsl.line_state, info.dsl.line_state_detail,
252                                                 info.dsl.line_state_num,
253                                                 info.dsl.line_mode_s,
254                                                 info.dsl.annex_s,
255                                                 info.dsl.profile_s,
256                                                 info.dsl.data_rate_down_s, info.dsl.data_rate_up_s,
257                                                 info.dsl.max_data_rate_down_s, info.dsl.max_data_rate_up_s,
258                                                 info.dsl.latency_num_down, info.dsl.latency_num_up,
259                                                 info.dsl.line_attenuation_down, info.dsl.line_attenuation_up,
260                                                 info.dsl.signal_attenuation_down, info.dsl.signal_attenuation_up,
261                                                 info.dsl.noise_margin_down, info.dsl.noise_margin_up,
262                                                 info.dsl.actatp_down, info.dsl.actatp_up,
263                                                 info.dsl.errors_fec_near, info.dsl.errors_fec_far,
264                                                 info.dsl.errors_es_near, info.dsl.errors_es_far,
265                                                 info.dsl.errors_ses_near, info.dsl.errors_ses_far,
266                                                 info.dsl.errors_loss_near, info.dsl.errors_loss_far,
267                                                 info.dsl.errors_uas_near, info.dsl.errors_uas_far,
268                                                 info.dsl.errors_hec_near, info.dsl.errors_hec_far,
269                                                 info.dsl.errors_crc_p_near, info.dsl.errors_crc_p_far,
270                                                 info.dsl.errors_crcp_p_near, info.dsl.errors_crcp_p_far,
271                                                 info.dsl.line_uptime_s,
272                                                 info.dsl.atuc_vendor_id,
273                                                 info.dsl.power_mode_s
274                                 );
275
276                                 dsl_s.innerHTML = String.format('<small>%s</small>', s);
277                                 dsl_i.innerHTML = String.format(
278                                         '<img src="<%=resource%>/icons/ethernet.png" />' +
279                                         '<br /><small>DSL</small>'
280                                 );
281                         <% end %>
282
283                         <% if has_wifi then %>
284                         var ws = document.getElementById('wifi_status_table');
285                         if (ws)
286                         {
287                                 while (ws.lastElementChild)
288                                         ws.removeChild(ws.lastElementChild);
289
290                                 for (var didx = 0; didx < info.wifinets.length; didx++)
291                                 {
292                                         var dev = info.wifinets[didx];
293                                         var net0 = (dev.networks && dev.networks[0]) ? dev.networks[0] : {};
294                                         var vifs = [];
295
296                                         for (var nidx = 0; nidx < dev.networks.length; nidx++)
297                                         {
298                                                 var net = dev.networks[nidx];
299                                                 var is_assoc = (net.bssid != '00:00:00:00:00:00' && net.channel && !net.disabled);
300
301                                                 var icon;
302                                                 if (!is_assoc)
303                                                         icon = "<%=resource%>/icons/signal-none.png";
304                                                 else if (net.quality == 0)
305                                                         icon = "<%=resource%>/icons/signal-0.png";
306                                                 else if (net.quality < 25)
307                                                         icon = "<%=resource%>/icons/signal-0-25.png";
308                                                 else if (net.quality < 50)
309                                                         icon = "<%=resource%>/icons/signal-25-50.png";
310                                                 else if (net.quality < 75)
311                                                         icon = "<%=resource%>/icons/signal-50-75.png";
312                                                 else
313                                                         icon = "<%=resource%>/icons/signal-75-100.png";
314
315                                                 vifs.push(renderBadge(
316                                                         icon,
317                                                         '<%:Signal%>: %d dBm / <%:Quality%>: %d%%'.format(net.signal, net.quality),
318                                                         '<%:SSID%>', E('a', { href: net.link }, [ net.ssid || '?' ]),
319                                                         '<%:Mode%>', net.mode,
320                                                         '<%:BSSID%>', is_assoc ? (net.bssid || '-') : null,
321                                                         '<%:Encryption%>', is_assoc ? net.encryption : null,
322                                                         '<%:Associations%>', is_assoc ? (net.num_assoc || '-') : null,
323                                                         null, is_assoc ? null : E('em', '<%:Wireless is disabled or not associated%>')));
324                                         }
325
326                                         ws.appendChild(renderBox(
327                                                 dev.device, dev.up || net0.up,
328                                                 [ E('div', vifs) ],
329                                                 '<%:Type%>', dev.name.replace(/^Generic | Wireless Controller .+$/g, ''),
330                                                 '<%:Channel%>', net0.channel ? '%d (%.3f <%:GHz%>)'.format(net0.channel, net0.frequency) : '-',
331                                                 '<%:Bitrate%>', net0.bitrate ? '%d <%:Mbit/s%>'.format(net0.bitrate) : '-'));
332                                 }
333
334                                 if (!ws.lastElementChild)
335                                         ws.appendChild(E('<em><%:No information available%></em>'));
336                         }
337                         <% end %>
338
339                         var e;
340
341                         if (e = document.getElementById('localtime'))
342                                 e.innerHTML = info.localtime;
343
344                         if (e = document.getElementById('uptime'))
345                                 e.innerHTML = String.format('%t', info.uptime);
346
347                         if (e = document.getElementById('loadavg'))
348                                 e.innerHTML = String.format(
349                                         '%.02f, %.02f, %.02f',
350                                         info.loadavg[0] / 65535.0,
351                                         info.loadavg[1] / 65535.0,
352                                         info.loadavg[2] / 65535.0
353                                 );
354
355                         if (e = document.getElementById('memtotal'))
356                                 e.innerHTML = progressbar(
357                                         ((info.memory.free + info.memory.buffered) / 1024) + " <%:kB%>",
358                                         (info.memory.total / 1024) + " <%:kB%>"
359                                 );
360
361                         if (e = document.getElementById('memfree'))
362                                 e.innerHTML = progressbar(
363                                         (info.memory.free / 1024) + " <%:kB%>",
364                                         (info.memory.total / 1024) + " <%:kB%>"
365                                 );
366
367                         if (e = document.getElementById('membuff'))
368                                 e.innerHTML = progressbar(
369                                         (info.memory.buffered / 1024) + " <%:kB%>",
370                                         (info.memory.total / 1024) + " <%:kB%>"
371                                 );
372
373                         if (e = document.getElementById('swaptotal'))
374                                 e.innerHTML = progressbar(
375                                         (info.swap.free / 1024) + " <%:kB%>",
376                                         (info.swap.total / 1024) + " <%:kB%>"
377                                 );
378
379                         if (e = document.getElementById('swapfree'))
380                                 e.innerHTML = progressbar(
381                                         (info.swap.free / 1024) + " <%:kB%>",
382                                         (info.swap.total / 1024) + " <%:kB%>"
383                                 );
384
385                         if (e = document.getElementById('conns'))
386                                 e.innerHTML = progressbar(info.conncount, info.connmax);
387
388                 }
389         );
390 //]]></script>
391
392 <h2 name="content"><%:Status%></h2>
393
394 <div class="cbi-section">
395         <h3><%:System%></h3>
396
397         <div class="table" width="100%">
398                 <div class="tr"><div class="td left" width="33%"><%:Hostname%></div><div class="td left"><%=luci.sys.hostname() or "?"%></div></div>
399                 <div class="tr"><div class="td left" width="33%"><%:Model%></div><div class="td left"><%=pcdata(boardinfo.model or "?")%></div></div>
400                 <div class="tr"><div class="td left" width="33%"><%:Architecture%></div><div class="td left"><%=pcdata(boardinfo.system or "?")%></div></div>
401                 <div class="tr"><div class="td left" width="33%"><%:Firmware Version%></div><div class="td left">
402                         <%=pcdata(ver.distname)%> <%=pcdata(ver.distversion)%> /
403                         <%=pcdata(ver.luciname)%> (<%=pcdata(ver.luciversion)%>)
404                 </div></div>
405                 <div class="tr"><div class="td left" width="33%"><%:Kernel Version%></div><div class="td left"><%=unameinfo.release or "?"%></div></div>
406                 <div class="tr"><div class="td left" width="33%"><%:Local Time%></div><div class="td left" id="localtime">-</div></div>
407                 <div class="tr"><div class="td left" width="33%"><%:Uptime%></div><div class="td left" id="uptime">-</div></div>
408                 <div class="tr"><div class="td left" width="33%"><%:Load Average%></div><div class="td left" id="loadavg">-</div></div>
409         </div>
410 </div>
411
412 <div class="cbi-section">
413         <h3><%:Memory%></h3>
414
415         <div class="table" width="100%">
416                 <div class="tr"><div class="td left" width="33%"><%:Total Available%></div><div class="td left" id="memtotal">-</div></div>
417                 <div class="tr"><div class="td left" width="33%"><%:Free%></div><div class="td left" id="memfree">-</div></div>
418                 <div class="tr"><div class="td left" width="33%"><%:Buffered%></div><div class="td left" id="membuff">-</div></div>
419         </div>
420 </div>
421
422 <% if swapinfo.total > 0 then %>
423 <div class="cbi-section">
424         <h3><%:Swap%></h3>
425
426         <div class="table" width="100%">
427                 <div class="tr"><div class="td left" width="33%"><%:Total Available%></div><div class="td left" id="swaptotal">-</div></div>
428                 <div class="tr"><div class="td left" width="33%"><%:Free%></div><div class="td left" id="swapfree">-</div></div>
429         </div>
430 </div>
431 <% end %>
432
433 <div class="cbi-section">
434         <h3><%:Network%></h3>
435
436         <div id="upstream_status_table" class="network-status-table">
437                 <p><em><%:Collecting data...%></em></p>
438         </div>
439
440         <div class="table" width="100%">
441                 <div class="tr"><div class="td left" width="33%"><%:Active Connections%></div><div class="td left" id="conns">-</div></div>
442         </div>
443 </div>
444
445 <%
446         if has_dhcp then
447                 include("admin_network/lease_status")
448         end
449 %>
450
451 <% if has_dsl then %>
452 <div class="cbi-section">
453         <h3><%:DSL%></h3>
454
455         <div class="table" width="100%">
456                 <div class="tr">
457                         <div class="td left" width="33%" style="vertical-align:top"><%:DSL Status%></div>
458                         <div class="td">
459                                 <div class="table">
460                                         <div class="tr">
461                                                 <div class="td" id="dsl_i" style="width:16px; text-align:center; padding:3px"><img src="<%=resource%>/icons/ethernet_disabled.png" /><br /><small>?</small></div>
462                                                 <div class="td left" id="dsl_s" style="vertical-align:middle; padding: 3px"><em><%:Collecting data...%></em></div>
463                                         </div>
464                                 </div>
465                         </div>
466                 </div>
467         </div>
468 </div>
469 <% end %>
470
471 <% if has_wifi then %>
472 <div class="cbi-section">
473         <h3><%:Wireless%></h3>
474
475         <div id="wifi_status_table" class="network-status-table">
476                 <p><em><%:Collecting data...%></em></p>
477         </div>
478 </div>
479
480 <div class="cbi-section">
481         <h3><%:Associated Stations%></h3>
482
483         <%+admin_network/wifi_assoclist%>
484 </div>
485 <% end %>
486
487 <%-
488         local incdir = util.libpath() .. "/view/admin_status/index/"
489         if fs.access(incdir) then
490                 local inc
491                 for inc in fs.dir(incdir) do
492                         if inc:match("%.htm$") then
493                                 include("admin_status/index/" .. inc:gsub("%.htm$", ""))
494                         end
495                 end
496         end
497 -%>
498
499 <%+footer%>