fix(reliability): recreate missing pineapd section; honest uci-set reporting
This commit is contained in:
@@ -31,8 +31,24 @@ def _pool_size():
|
|||||||
return len(out.split())
|
return len(out.split())
|
||||||
|
|
||||||
|
|
||||||
|
def _ensure_pineapd_section():
|
||||||
|
"""Stock daemon rewrites and profile restores can drop the whole
|
||||||
|
`config pineapd` section; every @pineapd[0] option write fails with
|
||||||
|
'Invalid argument' until it exists again."""
|
||||||
|
rc, out, err = device_run(['uci', '-q', 'get',
|
||||||
|
'pineapd.@pineapd[0].logrecon'])
|
||||||
|
if rc == 0:
|
||||||
|
return False
|
||||||
|
device_run(['uci', 'add', 'pineapd', 'pineapd'])
|
||||||
|
device_run(['uci', 'commit', 'pineapd'])
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def reconcile(clear_pool=True):
|
def reconcile(clear_pool=True):
|
||||||
changed = _apply_uci_wanted(_wanted())
|
changed = []
|
||||||
|
if _ensure_pineapd_section():
|
||||||
|
changed.append('pineapd.@pineapd[0] (section recreated)')
|
||||||
|
changed += _apply_uci_wanted(_wanted())
|
||||||
pool_cleared = False
|
pool_cleared = False
|
||||||
if clear_pool and _pool_size() > POOL_CLEAR_MAX:
|
if clear_pool and _pool_size() > POOL_CLEAR_MAX:
|
||||||
device_run(['uci', 'delete', 'pineapd.@ssidpool[0].ssid'])
|
device_run(['uci', 'delete', 'pineapd.@ssidpool[0].ssid'])
|
||||||
@@ -51,6 +67,7 @@ def guard_report():
|
|||||||
if cached is not None and now - _GR_CACHE['t'] < GR_TTL_SECONDS:
|
if cached is not None and now - _GR_CACHE['t'] < GR_TTL_SECONDS:
|
||||||
return cached
|
return cached
|
||||||
from server import _pending_uci
|
from server import _pending_uci
|
||||||
|
_ensure_pineapd_section()
|
||||||
pending = _pending_uci(_wanted())
|
pending = _pending_uci(_wanted())
|
||||||
report = {'in_sync': not pending, 'pending': pending,
|
report = {'in_sync': not pending, 'pending': pending,
|
||||||
'pool_size': _pool_size()}
|
'pool_size': _pool_size()}
|
||||||
|
|||||||
@@ -96,3 +96,50 @@ class GuardTest(unittest.TestCase):
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
||||||
|
|
||||||
|
class SectionRecreateTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.calls = []
|
||||||
|
self.uci = {}
|
||||||
|
self.old_server_run = server.device_run
|
||||||
|
self.old_iface = server._iface_up
|
||||||
|
server._iface_up = lambda name: True
|
||||||
|
|
||||||
|
def fake_run(args, timeout=20, input_data=None):
|
||||||
|
a = list(args)
|
||||||
|
self.calls.append(a)
|
||||||
|
if a[:4] == ['uci', '-q', 'get',
|
||||||
|
'pineapd.@pineapd[0].logrecon']:
|
||||||
|
return (1, '', '') # section missing
|
||||||
|
if a[:2] == ['uci', 'get']:
|
||||||
|
got = self.uci.get(a[2])
|
||||||
|
return (0, (got if got is not None else '') + '\n', '')
|
||||||
|
if a[:2] == ['uci', 'set']:
|
||||||
|
k, _, v = a[2].partition('=')
|
||||||
|
self.uci[k] = v
|
||||||
|
return (0, '', '')
|
||||||
|
|
||||||
|
def dual_run(args, timeout=20, input_data=None):
|
||||||
|
# install the same fake for server-side helpers
|
||||||
|
self.__dict__.setdefault('_srv', server)
|
||||||
|
return fake_run(args, timeout=timeout, input_data=input_data)
|
||||||
|
|
||||||
|
mk8_guard.device_run = fake_run
|
||||||
|
server.device_run = fake_run
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
server.device_run = self.old_server_run
|
||||||
|
server._iface_up = self.old_iface
|
||||||
|
|
||||||
|
def test_recreates_missing_pineapd_section(self):
|
||||||
|
result = mk8_guard.reconcile(clear_pool=False)
|
||||||
|
self.assertIn(['uci', 'add', 'pineapd', 'pineapd'], self.calls)
|
||||||
|
self.assertTrue(any('section recreated' in c for c in result['changed']))
|
||||||
|
sets = [c for c in self.calls if c[:2] == ['uci', 'set']]
|
||||||
|
self.assertEqual(len(sets),
|
||||||
|
len(server.PINEAPD_SAFE_UCI) - 1
|
||||||
|
+ len(mk8_guard.WANTED_EXTRA))
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user