From 3dc9a5538ed108eb5a1c1be19b40cf48dea4b71b Mon Sep 17 00:00:00 2001 From: scott Date: Thu, 16 Apr 2026 13:12:36 -0400 Subject: [PATCH] Show PercentComplete during firmware update task polling Previously only displayed TaskState. Now always fetches individual task detail URLs (where PercentComplete is available) and includes the percentage in the progress line, e.g. 'Running 42% [30s elapsed]'. Co-Authored-By: Claude Sonnet 4.6 --- modules/redfish.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/modules/redfish.py b/modules/redfish.py index c181392..c4e5fb6 100644 --- a/modules/redfish.py +++ b/modules/redfish.py @@ -130,7 +130,9 @@ def _redfish_trigger_update(password: str, host: str, target: str) -> tuple: def _redfish_poll_tasks(password: str, host: str, timeout: int = 600) -> tuple: """ Poll /redfish/v1/TaskService/Tasks/ until all tasks reach a terminal state - or timeout is exceeded. Returns (success: bool, message: str). + or timeout is exceeded. Fetches each task's detail URL to obtain + PercentComplete and displays live progress. + Returns (success: bool, message: str). """ TERMINAL = {"Completed", "Killed", "Exception"} deadline = time.monotonic() + timeout @@ -149,24 +151,30 @@ def _redfish_poll_tasks(password: str, host: str, timeout: int = 600) -> tuple: running = [] for member in members: - state = member.get("TaskState") + # Always fetch the individual task to get PercentComplete + task_path = member.get("@odata.id", "") + state = member.get("TaskState") + pct = member.get("PercentComplete") + + if task_path: + t_ok, t_data = _redfish_request( + password, "GET", task_path, host=host, + ) + if t_ok and isinstance(t_data, dict): + state = t_data.get("TaskState", state) + pct = t_data.get("PercentComplete", pct) + if state is None: - task_path = member.get("@odata.id", "") - if task_path: - t_ok, t_data = _redfish_request( - password, "GET", task_path, host=host, - ) - state = (t_data.get("TaskState") - if t_ok and isinstance(t_data, dict) else "Running") - else: - state = "Running" + state = "Running" + if state not in TERMINAL: - running.append(state) + pct_str = f" {pct}%" if pct is not None else "" + running.append(f"{state}{pct_str}") if not running: return True, "All tasks completed." - info(f" Tasks running ({', '.join(running)})... [{elapsed}s elapsed]") + info(f" Tasks in progress: {', '.join(running)} [{elapsed}s elapsed]") time.sleep(10) elapsed += 10