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:
|
for dev in self.disks:
|
||||||
disk_smart_status_check(dev, mid_run=True)
|
disk_smart_status_check(dev, mid_run=True)
|
||||||
for test in dev.tests:
|
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()
|
dev.disable_disk_tests()
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,28 @@ def get_smart_self_test_details(dev) -> dict[Any, Any]:
|
||||||
return details
|
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:
|
def monitor_smart_self_test(test_obj, header_str, log_path) -> bool:
|
||||||
"""Monitor SMART self-test status and update test_obj, returns bool."""
|
"""Monitor SMART self-test status and update test_obj, returns bool."""
|
||||||
started = False
|
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:
|
if _i * 5 >= SMART_SELF_TEST_START_TIMEOUT_IN_SECONDS:
|
||||||
# Test didn't start within limit, stop waiting
|
# Test didn't start within limit, stop waiting
|
||||||
abort_self_test(test_obj.dev)
|
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.failed = True
|
||||||
test_obj.set_status('TimedOut')
|
test_obj.set_status('TimedOut')
|
||||||
break
|
break
|
||||||
|
|
@ -290,7 +316,7 @@ def run_self_test(test_obj, log_path) -> None:
|
||||||
run_smart_self_test(test_obj, log_path)
|
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.
|
"""Run SMART self-test and check if it passed, returns bool.
|
||||||
|
|
||||||
NOTE: An exception will be raised if the disk lacks SMART support.
|
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
|
test_obj.failed = test_obj.failed or not test_obj.passed
|
||||||
|
|
||||||
# Set status
|
# 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')
|
test_obj.set_status('Failed')
|
||||||
elif test_obj.passed:
|
elif test_obj.passed:
|
||||||
test_obj.set_status('Passed')
|
test_obj.set_status('Passed')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue