fix(host_agent): disks behind a RAID controller each keep their own name (#5806)
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 1m24s
CI / unit (push) Successful in 1m32s
CI / publish (push) Successful in 1m6s

smartctl reports every disk behind a PERC/MegaRAID controller as /dev/bus/0
with type megaraid,N; the helper named a drive by its path alone, so all of
VDNT-Docker02's and Docker03's disks read as one drive "0", each overwriting
the last. The slot is now part of the name (bus0-megaraid3), and Steward gives
a repeated name an ordinal so two drives never share a series. Agent 1.20.1.

fix(ansible): Steward stopping mid-run logs no traceback (#5749)

The run's done-callback called exception() on a cancelled task, which raises;
it now logs a run cut short by shutdown at INFO. A finished run's in-memory
state is dropped by a timer rather than a sleeping task, which shutdown found
still pending.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 09:41:20 -04:00
co-authored by Claude Opus 5.5
parent 6c4ef368f9
commit e2055242f1
8 changed files with 138 additions and 19 deletions
+9 -6
View File
@@ -182,14 +182,17 @@ def deregister_listener(run_id: str, q: asyncio.Queue) -> None:
listeners.remove(q)
def _drop_run_state(run_id: str) -> None:
_run_lines.pop(run_id, None)
_run_done.pop(run_id, None)
def _schedule_cleanup(run_id: str) -> None:
"""Drop a finished run's in-memory state after a grace window."""
async def _cleanup() -> None:
await asyncio.sleep(_MEM_TTL_SECS)
_run_lines.pop(run_id, None)
_run_done.pop(run_id, None)
"""Drop a finished run's in-memory state after a grace window. A timer,
not a task (#5749): a run cut short by shutdown schedules this as the
loop closes, and a sleeping task would be destroyed while pending."""
try:
asyncio.create_task(_cleanup())
asyncio.get_running_loop().call_later(_MEM_TTL_SECS, _drop_run_state, run_id)
except RuntimeError:
pass # no running loop (e.g. tests) — fine to skip
+14 -5
View File
@@ -109,9 +109,18 @@ async def trigger_run(
connection=connection, secret_vars=secret_vars, redact=redact,
)
)
task.add_done_callback(
lambda t: t.exception() and app.logger.error(
"Ansible run %s raised: %s", run_id, t.exception()
)
)
task.add_done_callback(run_ended(app, run_id))
return run, source, None
def run_ended(app, run_id: str):
"""A run task's done-callback: an error is logged as one. A run cut short
by Steward stopping is not an error (#5749): `exception()` would raise
CancelledError on it, and the next start marks the run interrupted."""
def callback(t: asyncio.Task) -> None:
if t.cancelled():
app.logger.info("Ansible run %s interrupted: Steward is stopping; "
"it is marked interrupted at the next start", run_id)
elif t.exception() is not None:
app.logger.error("Ansible run %s raised: %s", run_id, t.exception())
return callback