diff --git a/status_panel.py b/status_panel.py index 019103a..fce13d3 100644 --- a/status_panel.py +++ b/status_panel.py @@ -1553,6 +1553,11 @@ def execute_fix(cfg, fix_id, chk): wake_on_lan(host["mac"], host.get("wake_broadcast")) log.info("FIX %s -> %s does not answer: Wake-on-LAN sent to %s", label, fix["host"], host["mac"]) return WAKING + if r.returncode == 255 and kind == "ssh": + # The machine itself is off the network (e.g. the Bible TV PC's Wi-Fi dropped, + # 2026-10-11): say so instead of a bare FIX FAILED. + log.info("FIX %s -> %s not reachable: %s", label, fix["host"], detail) + return "%s NOT\nREACHABLE" % fix.get("short", fix["host"].upper()) log.info("FIX %s -> %s%s", label, "ok" if r.returncode == 0 else "exit %d" % r.returncode, (": " + detail) if detail else "") conn = chk.get("conn") or fix.get("conn") diff --git a/tests/test_status_panel.py b/tests/test_status_panel.py index 5863b34..f33ba23 100644 --- a/tests/test_status_panel.py +++ b/tests/test_status_panel.py @@ -838,7 +838,8 @@ class TestFixes(unittest.TestCase): mock.patch.object(sp, "wake_on_lan", side_effect=lambda mac, bc=None: woke.append((mac, bc))): self.assertEqual(sp.execute_fix(CONFIG, "obs", {"conn": "OBS-Youtube"}), sp.WAKING) self.assertEqual(woke, [("6c:24:08:d7:fb:57", "10.1.255.255")]) - self.assertFalse(sp.execute_fix(CONFIG, "arena", {"conn": "arena"})) # no MAC: just fails + self.assertEqual(sp.execute_fix(CONFIG, "arena", {"conn": "arena"}), # no MAC: says so + "ARENA NOT\nREACHABLE") self.assertEqual(len(woke), 1) # the button says so self.snap.conns["OBS-Youtube"]["category"] = "error" @@ -848,6 +849,15 @@ class TestFixes(unittest.TestCase): time.sleep(0.2) self.assertEqual(self.engine.step(self.snap, time.time())["obs"]["x"], "OBS\nWAKING PC\nOBS") + def test_an_unreachable_pc_is_named_not_failed(self): + from unittest import mock + gone = mock.Mock(returncode=255, stdout="", stderr="ssh: connect to host 10.6.7.13 port 22: Operation timed out") + with mock.patch.object(sp.subprocess, "run", return_value=gone): + self.assertEqual(sp.execute_fix(CONFIG, "bibleapp", {}), "BIBLE APP NOT\nREACHABLE") + refused = mock.Mock(returncode=1, stdout="", stderr="") # reached it, the command failed + with mock.patch.object(sp.subprocess, "run", return_value=refused): + self.assertFalse(sp.execute_fix(CONFIG, "bibleapp", {})) + def test_magic_packet(self): from unittest import mock with mock.patch.object(sp.socket, "socket") as sock: