luci-base: network.js: add ability to flush the internal cache

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2019-07-31 08:33:52 +02:00
parent d1e9841e86
commit 3e5ef065df

View file

@ -84,11 +84,12 @@ var callNetworkDeviceStatus = rpc.declare({
}); });
var _cache = {}, var _cache = {},
_flush = true,
_state = null, _state = null,
_protocols = {}; _protocols = {};
function getWifiState() { function getWifiState(flush) {
if (_cache.wifi == null) if (_cache.wifi == null || flush)
return callNetworkWirelessStatus().then(function(state) { return callNetworkWirelessStatus().then(function(state) {
if (!L.isObject(state)) if (!L.isObject(state))
throw !1; throw !1;
@ -100,8 +101,8 @@ function getWifiState() {
return Promise.resolve(_cache.wifi); return Promise.resolve(_cache.wifi);
} }
function getInterfaceState() { function getInterfaceState(flush) {
if (_cache.interfacedump == null) if (_cache.interfacedump == null || flush)
return callNetworkInterfaceStatus().then(function(state) { return callNetworkInterfaceStatus().then(function(state) {
if (!Array.isArray(state)) if (!Array.isArray(state))
throw !1; throw !1;
@ -113,8 +114,8 @@ function getInterfaceState() {
return Promise.resolve(_cache.interfacedump); return Promise.resolve(_cache.interfacedump);
} }
function getDeviceState() { function getDeviceState(flush) {
if (_cache.devicedump == null) if (_cache.devicedump == null || flush)
return callNetworkDeviceStatus().then(function(state) { return callNetworkDeviceStatus().then(function(state) {
if (!L.isObject(state)) if (!L.isObject(state))
throw !1; throw !1;
@ -126,8 +127,8 @@ function getDeviceState() {
return Promise.resolve(_cache.devicedump); return Promise.resolve(_cache.devicedump);
} }
function getIfaddrState() { function getIfaddrState(flush) {
if (_cache.ifaddrs == null) if (_cache.ifaddrs == null || flush)
return callLuciIfaddrs().then(function(addrs) { return callLuciIfaddrs().then(function(addrs) {
if (!Array.isArray(addrs)) if (!Array.isArray(addrs))
throw !1; throw !1;
@ -139,8 +140,8 @@ function getIfaddrState() {
return Promise.resolve(_cache.ifaddrs); return Promise.resolve(_cache.ifaddrs);
} }
function getNetdevState() { function getNetdevState(flush) {
if (_cache.devices == null) if (_cache.devices == null || flush)
return callLuciNetdevs().then(function(state) { return callLuciNetdevs().then(function(state) {
if (!L.isObject(state)) if (!L.isObject(state))
throw !1; throw !1;
@ -152,8 +153,8 @@ function getNetdevState() {
return Promise.resolve(_cache.devices); return Promise.resolve(_cache.devices);
} }
function getBoardState() { function getBoardState(flush) {
if (_cache.board == null) if (_cache.board == null || flush)
return callLuciBoardjson().then(function(state) { return callLuciBoardjson().then(function(state) {
if (!L.isObject(state)) if (!L.isObject(state))
throw !1; throw !1;
@ -414,140 +415,149 @@ function maskToPrefix(mask, v6) {
} }
function initNetworkState() { function initNetworkState() {
if (_state == null) var flush = _flush;
return (_state = Promise.all([
getInterfaceState(), getDeviceState(), getBoardState(),
getWifiState(), getIfaddrState(), getNetdevState(),
uci.load('network'), uci.load('wireless'), uci.load('luci')
]).finally(function() {
var ifaddrs = _cache.ifaddrs,
devices = _cache.devices,
board = _cache.board,
s = { isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {}, interfaces: {}, bridges: {}, switches: {} };
for (var i = 0, a; (a = ifaddrs[i]) != null; i++) { _flush = false;
var name = a.name.replace(/:.+$/, '');
if (isVirtualIfname(name)) if (_state != null && !flush)
s.isTunnel[name] = true; return Promise.resolve(_state);
if (s.isTunnel[name] || !(isIgnoredIfname(name) || isVirtualIfname(name))) { if (_cache.pendingInit != null)
s.interfaces[name] = s.interfaces[name] || { return Promise.resolve(_cache.pendingInit);
idx: a.ifindex || i,
name: name,
rawname: a.name,
flags: [],
ipaddrs: [],
ip6addrs: []
};
if (a.family == 'packet') { return (_cache.pendingInit = Promise.all([
s.interfaces[name].flags = a.flags; getInterfaceState(flush), getDeviceState(flush), getBoardState(flush),
s.interfaces[name].stats = a.data; getWifiState(flush), getIfaddrState(flush), getNetdevState(flush), getProtocolHandlers(flush),
s.interfaces[name].macaddr = a.addr; uci.load('network'), uci.load('wireless'), uci.load('luci')
} ]).finally(function() {
else if (a.family == 'inet') { var ifaddrs = _cache.ifaddrs,
s.interfaces[name].ipaddrs.push(a.addr + '/' + a.netmask); devices = _cache.devices,
} board = _cache.board,
else if (a.family == 'inet6') { s = { isTunnel: {}, isBridge: {}, isSwitch: {}, isWifi: {}, interfaces: {}, bridges: {}, switches: {} };
s.interfaces[name].ip6addrs.push(a.addr + '/' + a.netmask);
} for (var i = 0, a; (a = ifaddrs[i]) != null; i++) {
var name = a.name.replace(/:.+$/, '');
if (isVirtualIfname(name))
s.isTunnel[name] = true;
if (s.isTunnel[name] || !(isIgnoredIfname(name) || isVirtualIfname(name))) {
s.interfaces[name] = s.interfaces[name] || {
idx: a.ifindex || i,
name: name,
rawname: a.name,
flags: [],
ipaddrs: [],
ip6addrs: []
};
if (a.family == 'packet') {
s.interfaces[name].flags = a.flags;
s.interfaces[name].stats = a.data;
s.interfaces[name].macaddr = a.addr;
}
else if (a.family == 'inet') {
s.interfaces[name].ipaddrs.push(a.addr + '/' + a.netmask);
}
else if (a.family == 'inet6') {
s.interfaces[name].ip6addrs.push(a.addr + '/' + a.netmask);
} }
} }
}
for (var devname in devices) { for (var devname in devices) {
var dev = devices[devname]; var dev = devices[devname];
if (dev.bridge) { if (dev.bridge) {
var b = { var b = {
name: devname, name: devname,
id: dev.id, id: dev.id,
stp: dev.stp, stp: dev.stp,
ifnames: [] ifnames: []
}; };
for (var i = 0; dev.ports && i < dev.ports.length; i++) { for (var i = 0; dev.ports && i < dev.ports.length; i++) {
var subdev = s.interfaces[dev.ports[i]]; var subdev = s.interfaces[dev.ports[i]];
if (subdev == null) if (subdev == null)
continue; continue;
b.ifnames.push(subdev); b.ifnames.push(subdev);
subdev.bridge = b; subdev.bridge = b;
}
s.bridges[devname] = b;
} }
s.bridges[devname] = b;
} }
}
if (L.isObject(board.switch)) { if (L.isObject(board.switch)) {
for (var switchname in board.switch) { for (var switchname in board.switch) {
var layout = board.switch[switchname], var layout = board.switch[switchname],
netdevs = {}, netdevs = {},
nports = {}, nports = {},
ports = [], ports = [],
pnum = null, pnum = null,
role = null; role = null;
if (L.isObject(layout) && Array.isArray(layout.ports)) { if (L.isObject(layout) && Array.isArray(layout.ports)) {
for (var i = 0, port; (port = layout.ports[i]) != null; i++) { for (var i = 0, port; (port = layout.ports[i]) != null; i++) {
if (typeof(port) == 'object' && typeof(port.num) == 'number' && if (typeof(port) == 'object' && typeof(port.num) == 'number' &&
(typeof(port.role) == 'string' || typeof(port.device) == 'string')) { (typeof(port.role) == 'string' || typeof(port.device) == 'string')) {
var spec = { var spec = {
num: port.num, num: port.num,
role: port.role || 'cpu', role: port.role || 'cpu',
index: (port.index != null) ? port.index : port.num index: (port.index != null) ? port.index : port.num
}; };
if (port.device != null) { if (port.device != null) {
spec.device = port.device; spec.device = port.device;
spec.tagged = spec.need_tag; spec.tagged = spec.need_tag;
netdevs[port.num] = port.device; netdevs[port.num] = port.device;
}
ports.push(spec);
if (port.role != null)
nports[port.role] = (nports[port.role] || 0) + 1;
}
}
ports.sort(function(a, b) {
if (a.role != b.role)
return (a.role < b.role) ? -1 : 1;
return (a.index - b.index);
});
for (var i = 0, port; (port = ports[i]) != null; i++) {
if (port.role != role) {
role = port.role;
pnum = 1;
} }
if (role == 'cpu') ports.push(spec);
port.label = 'CPU (%s)'.format(port.device);
else if (nports[role] > 1)
port.label = '%s %d'.format(role.toUpperCase(), pnum++);
else
port.label = role.toUpperCase();
delete port.role; if (port.role != null)
delete port.index; nports[port.role] = (nports[port.role] || 0) + 1;
}
}
ports.sort(function(a, b) {
if (a.role != b.role)
return (a.role < b.role) ? -1 : 1;
return (a.index - b.index);
});
for (var i = 0, port; (port = ports[i]) != null; i++) {
if (port.role != role) {
role = port.role;
pnum = 1;
} }
s.switches[switchname] = { if (role == 'cpu')
ports: ports, port.label = 'CPU (%s)'.format(port.device);
netdevs: netdevs else if (nports[role] > 1)
}; port.label = '%s %d'.format(role.toUpperCase(), pnum++);
else
port.label = role.toUpperCase();
delete port.role;
delete port.index;
} }
s.switches[switchname] = {
ports: ports,
netdevs: netdevs
};
} }
} }
}
return (_state = s); delete _cache.pendingInit;
}));
return Promise.resolve(_state); return (_state = s);
}));
} }
function ifnameOf(obj) { function ifnameOf(obj) {
@ -580,6 +590,12 @@ function deviceSort(a, b) {
var Network, Protocol, Device, WifiDevice, WifiNetwork; var Network, Protocol, Device, WifiDevice, WifiNetwork;
Network = L.Class.extend({ Network = L.Class.extend({
flushCache: function() {
return Promise.resolve(_state).then(function() {
_flush = true;
});
},
getProtocol: function(protoname, netname) { getProtocol: function(protoname, netname) {
var v = _protocols[protoname]; var v = _protocols[protoname];
if (v != null) if (v != null)