fix(reliability): converge runtime after profile restore (park dummy STA, re-raise monitors)
This commit is contained in:
@@ -4894,6 +4894,21 @@ def h_profile_save(ctx):
|
|||||||
return (200, {'ok': True}) if ok else (502, {'ok': False})
|
return (200, {'ok': True}) if ok else (502, {'ok': False})
|
||||||
|
|
||||||
|
|
||||||
|
def _post_restore_converge():
|
||||||
|
"""After any profile restore: re-apply invariants the restored config may
|
||||||
|
not carry. Factory-default configs enable dummy_radio0 (the phy0
|
||||||
|
channel-pinner) and may drop monitors; park and re-raise best-effort.
|
||||||
|
Uses ungated primitives — the restore is already inside its own gate."""
|
||||||
|
try:
|
||||||
|
_park_dummy_sta()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
_raise_monitors()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def h_profile_restore(ctx):
|
def h_profile_restore(ctx):
|
||||||
import mk8_events
|
import mk8_events
|
||||||
import mk8_gate
|
import mk8_gate
|
||||||
@@ -4911,6 +4926,7 @@ def h_profile_restore(ctx):
|
|||||||
ok = bool(result.get('ok'))
|
ok = bool(result.get('ok'))
|
||||||
if ok:
|
if ok:
|
||||||
device_run(['wifi', 'reload'], timeout=45)
|
device_run(['wifi', 'reload'], timeout=45)
|
||||||
|
_post_restore_converge()
|
||||||
try:
|
try:
|
||||||
mk8_events.log_event('profile_restore',
|
mk8_events.log_event('profile_restore',
|
||||||
sev='info' if ok else 'warn',
|
sev='info' if ok else 'warn',
|
||||||
@@ -5001,6 +5017,16 @@ def _sta_uplink_enabled():
|
|||||||
return cfg.get('mode') == 'sta' and cfg.get('disabled') != '1'
|
return cfg.get('mode') == 'sta' and cfg.get('disabled') != '1'
|
||||||
|
|
||||||
|
|
||||||
|
def _park_dummy_sta():
|
||||||
|
"""Ungated primitive: disable dummy_radio0 + take wlan0 down. Callers
|
||||||
|
that already run inside a gate (post-restore convergence) use this to
|
||||||
|
avoid spawning a nested watchdog."""
|
||||||
|
device_run(['uci', 'set', 'wireless.dummy_radio0.disabled=1'])
|
||||||
|
device_run(['uci', 'commit', 'wireless'])
|
||||||
|
for iface in ('wlan0',):
|
||||||
|
rc, out, err = device_run(['ip', 'link', 'set', iface, 'down'], timeout=10)
|
||||||
|
|
||||||
|
|
||||||
def _disable_sta_uplink():
|
def _disable_sta_uplink():
|
||||||
"""Disable the dummy_radio0 STA without bouncing the radios. The UCI flag
|
"""Disable the dummy_radio0 STA without bouncing the radios. The UCI flag
|
||||||
keeps it off across reboots/wifi reloads; taking wlan0 down immediately
|
keeps it off across reboots/wifi reloads; taking wlan0 down immediately
|
||||||
@@ -5008,10 +5034,7 @@ def _disable_sta_uplink():
|
|||||||
tears down live APs and drops the monitors mid-assessment."""
|
tears down live APs and drops the monitors mid-assessment."""
|
||||||
import mk8_gate
|
import mk8_gate
|
||||||
mk8_gate.enter('uplink_disable')
|
mk8_gate.enter('uplink_disable')
|
||||||
device_run(['uci', 'set', 'wireless.dummy_radio0.disabled=1'])
|
_park_dummy_sta()
|
||||||
device_run(['uci', 'commit', 'wireless'])
|
|
||||||
for iface in ('wlan0',):
|
|
||||||
rc, out, err = device_run(['ip', 'link', 'set', iface, 'down'], timeout=10)
|
|
||||||
|
|
||||||
|
|
||||||
def env_check():
|
def env_check():
|
||||||
@@ -7402,6 +7425,7 @@ if __name__ == '__main__':
|
|||||||
import mk8_profiles
|
import mk8_profiles
|
||||||
result = mk8_profiles.restore(name)
|
result = mk8_profiles.restore(name)
|
||||||
device_run(['wifi', 'reload'], timeout=90)
|
device_run(['wifi', 'reload'], timeout=90)
|
||||||
|
_post_restore_converge()
|
||||||
import mk8_events
|
import mk8_events
|
||||||
mk8_events.log_event('rollback', sev='warn',
|
mk8_events.log_event('rollback', sev='warn',
|
||||||
msg='watchdog restored %s' % name,
|
msg='watchdog restored %s' % name,
|
||||||
|
|||||||
@@ -208,6 +208,17 @@ class ReliabilityApiTest(unittest.TestCase):
|
|||||||
self.assertEqual(calls['restored'], 'p1')
|
self.assertEqual(calls['restored'], 'p1')
|
||||||
reloads = [r for r in self.runs if r[0][:2] == ['wifi', 'reload']]
|
reloads = [r for r in self.runs if r[0][:2] == ['wifi', 'reload']]
|
||||||
self.assertEqual(len(reloads), 1)
|
self.assertEqual(len(reloads), 1)
|
||||||
|
# post-restore convergence parks the factory-enabled dummy STA
|
||||||
|
parked = [r for r in self.runs
|
||||||
|
if r[0][:3] == ['uci', 'set',
|
||||||
|
'wireless.dummy_radio0.disabled=1']]
|
||||||
|
self.assertEqual(len(parked), 1)
|
||||||
|
downs = [r for r in self.runs if r[0][:4] == ['ip', 'link',
|
||||||
|
'set', 'wlan0']]
|
||||||
|
self.assertTrue(downs)
|
||||||
|
raises = [r for r in self.runs if r[0][:4] == ['ip', 'link',
|
||||||
|
'set', 'wlan0mon']]
|
||||||
|
self.assertTrue(raises)
|
||||||
self.assertEqual(calls['events'][-1][0], 'profile_restore')
|
self.assertEqual(calls['events'][-1][0], 'profile_restore')
|
||||||
|
|
||||||
status, result = server.h_profile_restore(
|
status, result = server.h_profile_restore(
|
||||||
|
|||||||
Reference in New Issue
Block a user