Refactor SMART self-test checks
- Preserve TimedOut status - Adds last self-test result to notes (if present and result is unknown)
This commit is contained in:
parent
96136e8e46
commit
59d89575ed
2 changed files with 38 additions and 3 deletions
|
|
@ -118,7 +118,13 @@ class State():
|
|||
for dev in self.disks:
|
||||
disk_smart_status_check(dev, mid_run=True)
|
||||
for test in dev.tests:
|
||||
if test.failed and 'Attributes' not in test.name:
|
||||
if test.failed:
|
||||
# Skip acceptable failure states
|
||||
if 'Attributes' in test.name:
|
||||
continue
|
||||
if 'Self-Test' in test.name and 'TimedOut' in test.status:
|
||||
continue
|
||||
# Disable remaining tests
|
||||
dev.disable_disk_tests()
|
||||
break
|
||||
|
||||
|
|
|
|||
|
|
@ -231,6 +231,28 @@ def get_smart_self_test_details(dev) -> dict[Any, Any]:
|
|||
return details
|
||||
|
||||
|
||||
def get_smart_self_test_last_result(dev) -> str:
|
||||
"""Get last SMART self-test result, returns str."""
|
||||
result = 'Unknown'
|
||||
|
||||
# Parse SMART data
|
||||
data = dev.raw_smartctl.get('ata_smart_self_test_log', {}).get('standard', {}).get('table', [])
|
||||
if not data:
|
||||
# No results found
|
||||
return result
|
||||
|
||||
# Build result string
|
||||
result = (
|
||||
f'Power-on hours: {data.get("lifetime_hours", "?")}'
|
||||
f', Type: {data.get("type", {}).get("string", "?")}'
|
||||
f', Passed: {data.get("status", {}).get("passed", "?")}'
|
||||
f', Result: {data.get("status", {}).get("string", "?")}'
|
||||
)
|
||||
|
||||
# Done
|
||||
return result
|
||||
|
||||
|
||||
def monitor_smart_self_test(test_obj, header_str, log_path) -> bool:
|
||||
"""Monitor SMART self-test status and update test_obj, returns bool."""
|
||||
started = False
|
||||
|
|
@ -262,6 +284,10 @@ def monitor_smart_self_test(test_obj, header_str, log_path) -> bool:
|
|||
if _i * 5 >= SMART_SELF_TEST_START_TIMEOUT_IN_SECONDS:
|
||||
# Test didn't start within limit, stop waiting
|
||||
abort_self_test(test_obj.dev)
|
||||
result = get_smart_self_test_last_result(test_obj.dev)
|
||||
if result == 'Unknown':
|
||||
result = 'SMART self-test failed to start'
|
||||
test_obj.dev.add_note(result)
|
||||
test_obj.failed = True
|
||||
test_obj.set_status('TimedOut')
|
||||
break
|
||||
|
|
@ -290,7 +316,7 @@ def run_self_test(test_obj, log_path) -> None:
|
|||
run_smart_self_test(test_obj, log_path)
|
||||
|
||||
|
||||
def run_smart_self_test(test_obj, log_path) -> bool:
|
||||
def run_smart_self_test(test_obj, log_path) -> None:
|
||||
"""Run SMART self-test and check if it passed, returns bool.
|
||||
|
||||
NOTE: An exception will be raised if the disk lacks SMART support.
|
||||
|
|
@ -352,7 +378,10 @@ def run_smart_self_test(test_obj, log_path) -> bool:
|
|||
test_obj.failed = test_obj.failed or not test_obj.passed
|
||||
|
||||
# Set status
|
||||
if test_obj.failed and test_obj.status != 'TimedOut':
|
||||
if test_obj.status == 'TimedOut':
|
||||
# Preserve TimedOut status
|
||||
pass
|
||||
elif test_obj.failed:
|
||||
test_obj.set_status('Failed')
|
||||
elif test_obj.passed:
|
||||
test_obj.set_status('Passed')
|
||||
|
|
|
|||
Loading…
Reference in a new issue