Skip to content

Commit

Permalink
luci-mod-status: reimplement index status page as client side view
Browse files Browse the repository at this point in the history
Signed-off-by: Jo-Philipp Wich <[email protected]>
  • Loading branch information
jow- committed Nov 1, 2019
1 parent 5ce1676 commit c85af3d
Show file tree
Hide file tree
Showing 15 changed files with 754 additions and 484 deletions.
9 changes: 6 additions & 3 deletions modules/luci-base/root/usr/share/rpcd/acl.d/luci-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,18 @@
"/proc/mtd": [ "read" ],
"/proc/partitions": [ "read" ],
"/proc/sys/kernel/hostname": [ "read" ],
"/proc/mounts": [ "read" ]
"/proc/sys/net/netfilter/nf_conntrack_*": [ "read" ],
"/proc/mounts": [ "read" ],
"/usr/lib/lua/luci/version.lua": [ "read" ]
},
"ubus": {
"file": [ "list", "read", "stat" ],
"iwinfo": [ "assoclist", "freqlist", "txpowerlist", "countrylist" ],
"luci": [ "getDUIDHints", "getInitList", "getLocaltime", "getTimezones", "getLEDs", "getUSBDevices", "getSwconfigFeatures", "getSwconfigPortState", "getBlockDevices", "getMountPoints" ],
"luci-rpc": [ "getBoardJSON", "getDHCPLeases", "getHostHints", "getNetworkDevices", "getWirelessDevices" ],
"luci-rpc": [ "getBoardJSON", "getDHCPLeases", "getDSLStatus", "getHostHints", "getNetworkDevices", "getWirelessDevices" ],
"network.interface": [ "dump" ],
"network": [ "get_proto_handlers" ],
"system": [ "validate_firmware_image" ],
"system": [ "board", "info", "validate_firmware_image" ],
"uci": [ "changes", "get" ]
},
"uci": [ "*" ]
Expand All @@ -69,6 +71,7 @@
},
"ubus": {
"file": [ "write", "remove", "exec" ],
"hostapd.*": [ "del_client" ],
"iwinfo": [ "scan" ],
"luci": [ "setInitAction", "setLocaltime", "setPassword", "setBlockDetect" ],
"uci": [ "add", "apply", "confirm", "delete", "order", "set", "rename" ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
'use strict';
'require fs';
'require rpc';

var callSystemBoard = rpc.declare({
object: 'system',
method: 'board'
});

var callSystemInfo = rpc.declare({
object: 'system',
method: 'info'
});

return L.Class.extend({
title: _('System'),

load: function() {
return Promise.all([
L.resolveDefault(callSystemBoard(), {}),
L.resolveDefault(callSystemInfo(), {}),
fs.lines('/usr/lib/lua/luci/version.lua')
]);
},

render: function(data) {
var boardinfo = data[0],
systeminfo = data[1],
luciversion = data[2];

luciversion = luciversion.filter(function(l) {
return l.match(/^\s*(luciname|luciversion)\s*=/);
}).map(function(l) {
return l.replace(/^\s*\w+\s*=\s*['"]([^'"]+)['"].*$/, '$1');
}).join(' ');

var fields = [
_('Hostname'), boardinfo.hostname,
_('Model'), boardinfo.model,
_('Architecture'), boardinfo.system,
_('Firmware Version'), (L.isObject(boardinfo.release) ? boardinfo.release.description + ' / ' : '') + (luciversion || ''),
_('Kernel Version'), boardinfo.kernel,
_('Local Time'), systeminfo.localtime ? (new Date(systeminfo.localtime * 1000)).toLocaleString() : null,
_('Uptime'), systeminfo.uptime ? '%t'.format(systeminfo.uptime) : null,
_('Load Average'), Array.isArray(systeminfo.load) ? '%.2f, %.2f, %.2f'.format(
systeminfo.load[0] / 65535.0,
systeminfo.load[1] / 65535.0,
systeminfo.load[2] / 65535.0
) : null
];

var table = E('div', { 'class': 'table' });

for (var i = 0; i < fields.length; i += 2) {
table.appendChild(E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left', 'width': '33%' }, [ fields[i] ]),
E('div', { 'class': 'td left' }, [ (fields[i + 1] != null) ? fields[i + 1] : '?' ])
]));
}

return table;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';
'require rpc';

var callSystemInfo = rpc.declare({
object: 'system',
method: 'info'
});

function progressbar(value, max, byte) {
var vn = parseInt(value) || 0,
mn = parseInt(max) || 100,
fv = byte ? String.format('%1024.2mB', value) : value,
fm = byte ? String.format('%1024.2mB', max) : max,
pc = Math.floor((100 / mn) * vn);

return E('div', {
'class': 'cbi-progressbar',
'title': '%s / %s (%d%%)'.format(fv, fm, pc)
}, E('div', { 'style': 'width:%.2f%%'.format(pc) }));
}

return L.Class.extend({
title: _('Memory'),

load: function() {
return L.resolveDefault(callSystemInfo(), {});
},

render: function(systeminfo) {
var mem = L.isObject(systeminfo.memory) ? systeminfo.memory : {},
swap = L.isObject(systeminfo.swap) ? systeminfo.swap : {};

var fields = [
_('Total Available'), (mem.total && mem.free && mem.buffered) ? mem.free + mem.buffered : null,
_('Free'), (mem.total && mem.free) ? mem.free : null,
_('Buffered'), (mem.total && mem.buffered) ? mem.buffered : null
];

if (swap.total > 0)
fields.push(_('Swap free'), swap.free);

var table = E('div', { 'class': 'table' });

for (var i = 0; i < fields.length; i += 2) {
table.appendChild(E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left', 'width': '33%' }, [ fields[i] ]),
E('div', { 'class': 'td left' }, [
(fields[i + 1] != null) ? progressbar(fields[i + 1], mem.total, true) : '?'
])
]));
}

return table;
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
'use strict';
'require fs';
'require network';

function progressbar(value, max, byte) {
var vn = parseInt(value) || 0,
mn = parseInt(max) || 100,
fv = byte ? String.format('%1024.2mB', value) : value,
fm = byte ? String.format('%1024.2mB', max) : max,
pc = Math.floor((100 / mn) * vn);

return E('div', {
'class': 'cbi-progressbar',
'title': '%s / %s (%d%%)'.format(fv, fm, pc)
}, E('div', { 'style': 'width:%.2f%%'.format(pc) }));
}

function renderbox(ifc, ipv6) {
var dev = ifc.getL3Device(),
active = (dev && ifc.getProtocol() != 'none'),
addrs = (ipv6 ? ifc.getIP6Addrs() : ifc.getIPAddrs()) || [],
dnssrv = (ipv6 ? ifc.getDNS6Addrs() : ifc.getDNSAddrs()) || [],
expires = (ipv6 ? null : ifc.getExpiry()),
uptime = ifc.getUptime();

return E('div', { class: 'ifacebox' }, [
E('div', { class: 'ifacebox-head center ' + (active ? 'active' : '') },
E('strong', ipv6 ? _('IPv6 Upstream') : _('IPv4 Upstream'))),
E('div', { class: 'ifacebox-body left' }, [
L.itemlist(E('span'), [
_('Protocol'), ifc.getI18n() || E('em', _('Not connected')),
_('Prefix Delegated'), ipv6 ? ifc.getIP6Prefix() : null,
_('Address'), addrs[0],
_('Address'), addrs[1],
_('Address'), addrs[2],
_('Address'), addrs[3],
_('Address'), addrs[4],
_('Address'), addrs[5],
_('Address'), addrs[6],
_('Address'), addrs[7],
_('Address'), addrs[8],
_('Address'), addrs[9],
_('Gateway'), ipv6 ? (ifc.getGateway6Addr() || '::') : (ifc.getGatewayAddr() || '0.0.0.0'),
_('DNS') + ' 1', dnssrv[0],
_('DNS') + ' 2', dnssrv[1],
_('DNS') + ' 3', dnssrv[2],
_('DNS') + ' 4', dnssrv[3],
_('DNS') + ' 5', dnssrv[4],
_('Expires'), (expires != null && expires > -1) ? '%t'.format(expires) : null,
_('Connected'), (uptime > 0) ? '%t'.format(uptime) : null
]),
E('div', {}, renderBadge(
L.resource('icons/%s.png').format(dev ? dev.getType() : 'ethernet_disabled'), null,
_('Device'), dev ? dev.getI18n() : '-',
_('MAC-Address'), dev.getMAC())
)
])
]);
}

return L.Class.extend({
title: _('Network'),

load: function() {
return Promise.all([
fs.trimmed('/proc/sys/net/netfilter/nf_conntrack_count'),
fs.trimmed('/proc/sys/net/netfilter/nf_conntrack_max'),
network.getWANNetworks(),
network.getWAN6Networks()
]);
},

render: function(data) {
var ct_count = +data[0],
ct_max = +data[1],
wan_nets = data[2],
wan6_nets = data[3];

var fields = [
_('Active Connections'), ct_max ? ct_count : null
];

var ctstatus = E('div', { 'class': 'table' });

for (var i = 0; i < fields.length; i += 2) {
ctstatus.appendChild(E('div', { 'class': 'tr' }, [
E('div', { 'class': 'td left', 'width': '33%' }, [ fields[i] ]),
E('div', { 'class': 'td left' }, [
(fields[i + 1] != null) ? progressbar(fields[i + 1], ct_max) : '?'
])
]));
}

var netstatus = E('div', { 'class': 'network-status-table' });

for (var i = 0; i < wan_nets.length; i++)
netstatus.appendChild(renderbox(wan_nets[i], false));

for (var i = 0; i < wan6_nets.length; i++)
netstatus.appendChild(renderbox(wan6_nets[i], true));

return E([
netstatus,
ctstatus
]);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
'use strict';
'require rpc';
'require network';

var callLuciDHCPLeases = rpc.declare({
object: 'luci-rpc',
method: 'getDHCPLeases',
expect: { '': {} }
});

return L.Class.extend({
title: _('Active DHCP Leases'),

load: function() {
return Promise.all([
L.resolveDefault(callLuciDHCPLeases(), {}),
network.getHostHints()
]);
},

render: function(data) {
var leases = Array.isArray(data[0].dhcp_leases) ? data[0].dhcp_leases : [],
leases6 = Array.isArray(data[0].dhcp6_leases) ? data[0].dhcp6_leases : [],
machints = data[1].getMACHints(false);

var table = E('div', { 'class': 'table' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th' }, _('Hostname')),
E('div', { 'class': 'th' }, _('IPv4-Address')),
E('div', { 'class': 'th' }, _('MAC-Address')),
E('div', { 'class': 'th' }, _('Leasetime remaining'))
])
]);

cbi_update_table(table, leases.map(function(lease) {
var exp;

if (lease.expires === false)
exp = E('em', _('unlimited'));
else if (lease.expires <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.expires);

return [
lease.hostname || '-',
lease.ipaddr,
lease.macaddr,
exp
];
}), E('em', _('There are no active leases')));

var table6 = E('div', { 'class': 'table' }, [
E('div', { 'class': 'tr table-titles' }, [
E('div', { 'class': 'th' }, _('Host')),
E('div', { 'class': 'th' }, _('IPv6-Address')),
E('div', { 'class': 'th' }, _('DUID')),
E('div', { 'class': 'th' }, _('Leasetime remaining'))
])
]);

cbi_update_table(table6, leases6.map(function(lease) {
var exp;

if (lease.expires === false)
exp = E('em', _('unlimited'));
else if (lease.expires <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.expires);

var hint = lease.macaddr ? machints.filter(function(h) { return h[0] == lease.macaddr })[0] : null,
host = null;

if (hint && lease.hostname && lease.hostname != hint[1] && lease.ip6addr != hint[1])
host = '%s (%s)'.format(lease.hostname, hint[1]);
else if (lease.hostname)
host = lease.hostname;
else if (hint)
host = hint[1];

return [
host || '-',
lease.ip6addr,
lease.duid,
exp
];
}), E('em', _('There are no active leases')));

return E([
table,
E('h3', _('Active DHCPv6 Leases')),
table6
]);
}
});
Loading

0 comments on commit c85af3d

Please sign in to comment.