fix(reliability): supervisor re-parks stock-resurrected dummy STA on interval
This commit is contained in:
@@ -4719,6 +4719,7 @@ def _mem_percent(path='/proc/meminfo'):
|
||||
|
||||
MEM_WARN_PERCENT = 85
|
||||
MEM_WARN_STREAK = 5
|
||||
HEALTH_STA_PARK_INTERVAL = 4 # every Nth health tick (~1/min at 15s poll)
|
||||
|
||||
|
||||
def health_check():
|
||||
@@ -4755,6 +4756,21 @@ def health_check():
|
||||
# does not bring secondary monitors back). Repair them without cooldown.
|
||||
if _monitor_down('wlan1mon') or _monitor_down('wlan0mon'):
|
||||
_bring_monitors_up(h)
|
||||
# The stock daemon re-enables its dummy STA during its own config
|
||||
# reconvergence (e.g. after wifi reloads), silently pinning phy0 again.
|
||||
# Re-park periodically — parking never runs wifi reload, so it is safe
|
||||
# to repeat.
|
||||
h['ticks'] = h.get('ticks', 0) + 1
|
||||
if h['ticks'] % HEALTH_STA_PARK_INTERVAL == 0 and _sta_uplink_enabled():
|
||||
try:
|
||||
_park_dummy_sta()
|
||||
h['last_action'] = 'dummy STA re-parked'
|
||||
import mk8_events
|
||||
mk8_events.log_event('guard_fix',
|
||||
msg='re-parked dummy_radio0 STA '
|
||||
'(stock reconvergence)')
|
||||
except Exception:
|
||||
pass
|
||||
h['mem_percent'] = _mem_percent()
|
||||
if h['mem_percent'] >= MEM_WARN_PERCENT:
|
||||
h['mem_streak'] = h.get('mem_streak', 0) + 1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'payload', 'user', 'remote_access', 'pager-webui'))
|
||||
import server
|
||||
@@ -150,6 +151,25 @@ class SupervisorExtrasTest(unittest.TestCase):
|
||||
open(path, 'w').write(content)
|
||||
self.assertEqual(server._mem_percent(path), 60)
|
||||
|
||||
def test_health_reparks_resurrected_dummy_sta(self):
|
||||
server._health['ticks'] = server.HEALTH_STA_PARK_INTERVAL - 1
|
||||
with mock.patch.object(
|
||||
server, '_sta_uplink_enabled', return_value=True), \
|
||||
__import__('unittest').mock.patch.object(
|
||||
server, '_park_dummy_sta') as park:
|
||||
h = server.health_check()
|
||||
park.assert_called_once()
|
||||
self.assertEqual(server._health['ticks'],
|
||||
server.HEALTH_STA_PARK_INTERVAL)
|
||||
# not on interval ticks: no re-park
|
||||
server._health['ticks'] = 1
|
||||
with mock.patch.object(
|
||||
server, '_sta_uplink_enabled', return_value=True), \
|
||||
__import__('unittest').mock.patch.object(
|
||||
server, '_park_dummy_sta') as park:
|
||||
server.health_check()
|
||||
park.assert_not_called()
|
||||
|
||||
def test_health_reports_events_and_counters(self):
|
||||
import mk8_events
|
||||
mk8_events.log_event('restart', msg='x')
|
||||
|
||||
Reference in New Issue
Block a user