mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-29 02:46:38 +00:00
Update flask_server.py
This commit is contained in:
@@ -6698,21 +6698,27 @@ def api_smart_status(disk_name):
|
|||||||
def api_smart_run_test(disk_name):
|
def api_smart_run_test(disk_name):
|
||||||
"""Start a SMART self-test on a disk."""
|
"""Start a SMART self-test on a disk."""
|
||||||
try:
|
try:
|
||||||
|
logging.info(f"[SMART Test] Starting test for disk: {disk_name}")
|
||||||
|
|
||||||
# Validate disk name (security)
|
# Validate disk name (security)
|
||||||
if not re.match(r'^[a-zA-Z0-9]+$', disk_name):
|
if not re.match(r'^[a-zA-Z0-9]+$', disk_name):
|
||||||
|
logging.warning(f"[SMART Test] Invalid disk name rejected: {disk_name}")
|
||||||
return jsonify({'error': 'Invalid disk name'}), 400
|
return jsonify({'error': 'Invalid disk name'}), 400
|
||||||
|
|
||||||
device = f'/dev/{disk_name}'
|
device = f'/dev/{disk_name}'
|
||||||
if not os.path.exists(device):
|
if not os.path.exists(device):
|
||||||
|
logging.warning(f"[SMART Test] Device not found: {device}")
|
||||||
return jsonify({'error': 'Device not found'}), 404
|
return jsonify({'error': 'Device not found'}), 404
|
||||||
|
|
||||||
data = request.get_json() or {}
|
data = request.get_json() or {}
|
||||||
test_type = data.get('test_type', 'short')
|
test_type = data.get('test_type', 'short')
|
||||||
|
logging.info(f"[SMART Test] Test type: {test_type}, Device: {device}")
|
||||||
|
|
||||||
if test_type not in ('short', 'long'):
|
if test_type not in ('short', 'long'):
|
||||||
return jsonify({'error': 'Invalid test type. Use "short" or "long"'}), 400
|
return jsonify({'error': 'Invalid test type. Use "short" or "long"'}), 400
|
||||||
|
|
||||||
is_nvme = _is_nvme(disk_name)
|
is_nvme = _is_nvme(disk_name)
|
||||||
|
logging.info(f"[SMART Test] Is NVMe: {is_nvme}")
|
||||||
|
|
||||||
# Check tools and auto-install if missing
|
# Check tools and auto-install if missing
|
||||||
tools = _ensure_smart_tools(install_if_missing=True)
|
tools = _ensure_smart_tools(install_if_missing=True)
|
||||||
@@ -6728,7 +6734,7 @@ def api_smart_run_test(disk_name):
|
|||||||
# NVMe: self-test-code 1=short, 2=long
|
# NVMe: self-test-code 1=short, 2=long
|
||||||
code = 1 if test_type == 'short' else 2
|
code = 1 if test_type == 'short' else 2
|
||||||
|
|
||||||
# First check if device supports self-test
|
# First check if device is accessible
|
||||||
check_proc = subprocess.run(
|
check_proc = subprocess.run(
|
||||||
['nvme', 'id-ctrl', device],
|
['nvme', 'id-ctrl', device],
|
||||||
capture_output=True, text=True, timeout=10
|
capture_output=True, text=True, timeout=10
|
||||||
@@ -6736,24 +6742,48 @@ def api_smart_run_test(disk_name):
|
|||||||
if check_proc.returncode != 0:
|
if check_proc.returncode != 0:
|
||||||
return jsonify({'error': f'Cannot access NVMe device: {check_proc.stderr.strip() or "Device not responding"}'}), 500
|
return jsonify({'error': f'Cannot access NVMe device: {check_proc.stderr.strip() or "Device not responding"}'}), 500
|
||||||
|
|
||||||
|
# Check if device supports self-test by looking at OACS field
|
||||||
|
# OACS bit 4 (0x10) indicates Device Self-test support
|
||||||
|
oacs_output = check_proc.stdout
|
||||||
|
supports_selftest = True # Assume supported by default
|
||||||
|
for line in oacs_output.split('\n'):
|
||||||
|
if 'oacs' in line.lower():
|
||||||
|
try:
|
||||||
|
# Parse OACS value (usually in hex)
|
||||||
|
oacs_val = int(line.split(':')[-1].strip(), 0)
|
||||||
|
if not (oacs_val & 0x10):
|
||||||
|
supports_selftest = False
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
pass
|
||||||
|
break
|
||||||
|
|
||||||
|
if not supports_selftest:
|
||||||
|
return jsonify({'error': 'This NVMe device does not support self-test (OACS bit 4 not set)'}), 400
|
||||||
|
|
||||||
|
logging.info(f"[SMART Test] Running: nvme device-self-test {device} --self-test-code={code}")
|
||||||
proc = subprocess.run(
|
proc = subprocess.run(
|
||||||
['nvme', 'device-self-test', device, f'--self-test-code={code}'],
|
['nvme', 'device-self-test', device, f'--self-test-code={code}'],
|
||||||
capture_output=True, text=True, timeout=30
|
capture_output=True, text=True, timeout=30
|
||||||
)
|
)
|
||||||
|
logging.info(f"[SMART Test] Result: returncode={proc.returncode}, stdout={proc.stdout[:200] if proc.stdout else ''}, stderr={proc.stderr[:200] if proc.stderr else ''}")
|
||||||
|
|
||||||
if proc.returncode != 0:
|
if proc.returncode != 0:
|
||||||
error_msg = proc.stderr.strip() or proc.stdout.strip() or 'Unknown error'
|
error_msg = proc.stderr.strip() or proc.stdout.strip() or 'Unknown error'
|
||||||
# Some NVMe devices don't support self-test
|
# Some NVMe devices don't support self-test
|
||||||
if 'not support' in error_msg.lower() or 'invalid' in error_msg.lower():
|
if 'not support' in error_msg.lower() or 'invalid' in error_msg.lower() or 'operation' in error_msg.lower():
|
||||||
return jsonify({'error': f'This NVMe device does not support self-test: {error_msg}'}), 400
|
return jsonify({'error': f'This NVMe device does not support self-test: {error_msg}'}), 400
|
||||||
|
# Check for permission errors
|
||||||
|
if 'permission' in error_msg.lower() or 'operation not permitted' in error_msg.lower():
|
||||||
|
return jsonify({'error': f'Permission denied. Run as root: {error_msg}'}), 403
|
||||||
return jsonify({'error': f'Failed to start test: {error_msg}'}), 500
|
return jsonify({'error': f'Failed to start test: {error_msg}'}), 500
|
||||||
|
|
||||||
# Start background monitor to save JSON when test completes
|
# Start background monitor to save JSON when test completes
|
||||||
|
# Use 'nvme self-test-log' to check test status (not device-self-test)
|
||||||
sleep_interval = 10 if test_type == 'short' else 60
|
sleep_interval = 10 if test_type == 'short' else 60
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
f'''
|
f'''
|
||||||
sleep 5
|
sleep 5
|
||||||
while nvme device-self-test {device} --self-test-code=0 2>/dev/null | grep -qi 'in progress'; do
|
while nvme self-test-log {device} 2>/dev/null | grep -qi 'in progress\\|operation in progress'; do
|
||||||
sleep {sleep_interval}
|
sleep {sleep_interval}
|
||||||
done
|
done
|
||||||
nvme smart-log -o json {device} > {json_path} 2>/dev/null
|
nvme smart-log -o json {device} > {json_path} 2>/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user