update 1.2.2.2 beta

This commit is contained in:
MacRimi
2026-07-02 18:12:13 +02:00
parent f0e79e93b6
commit bc3c771137
7 changed files with 402 additions and 30 deletions

View File

@@ -1586,10 +1586,18 @@ def internal_restore_event():
stale_nodes = data.get('stale_nodes', '0')
components = data.get('components', 'none')
duration = data.get('duration', 'unknown')
# Boot sanity-check warnings surfaced by apply_cluster_postboot.sh.
# Empty on a clean restore; populated on the cross-version path
# when the sanity check found something the operator should know
# about (missing /lib/modules for the default kernel, no ESP
# configured, dangling /vmlinuz, ...).
warnings = data.get('warnings', '').strip()
severity = 'WARNING' if warnings else 'INFO'
warnings_block = f'\n⚠️ Boot sanity: {warnings}\n' if warnings else ''
notification_manager.emit_event(
event_type='system_restore_completed',
severity='INFO',
severity=severity,
data={
'hostname': hostname,
'guests': guests,
@@ -1597,6 +1605,8 @@ def internal_restore_event():
'stale_nodes': stale_nodes,
'components': components,
'duration': duration,
'warnings': warnings,
'warnings_block': warnings_block,
},
source='proxmenux',
entity='node',

View File

@@ -9576,7 +9576,10 @@ def api_smart_run_test(disk_name):
capture_output=True, text=True, timeout=10
)
if check_proc.returncode != 0:
return jsonify({'error': f'Cannot access NVMe device: {check_proc.stderr.strip() or "Device not responding"}'}), 500
# Device-level failure, not a server bug — return 400 so
# the UI surfaces the real stderr instead of a generic
# "500 INTERNAL SERVER ERROR".
return jsonify({'error': f'Cannot access NVMe device: {check_proc.stderr.strip() or "Device not responding"}'}), 400
# Check if device supports self-test by looking at OACS field
# OACS bit 4 (0x10) indicates Device Self-test support
@@ -9616,8 +9619,8 @@ def api_smart_run_test(disk_name):
# 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}'}), 400
# Start background monitor to save JSON when test completes
# Check 'Current Device Self-Test Operation' field - if > 0, test is running
sleep_interval = 10 if test_type == 'short' else 60
@@ -9648,7 +9651,21 @@ def api_smart_run_test(disk_name):
)
if proc.returncode not in (0, 4): # 4 = test started successfully
return jsonify({'error': f'Failed to start test: {proc.stderr}'}), 500
# smartctl scribbles the useful diagnostic on stderr for
# most failures but some device-level errors (USB SATA
# bridges that reject the SMART command, drives whose
# ATA passthrough is broken, ...) print the reason on
# stdout instead. Concatenate both so the operator sees
# the real reason in the toast rather than an opaque
# "500 INTERNAL SERVER ERROR". Status is 400: the smartctl
# process ran fine, the device is what rejected the test.
err_detail = (proc.stderr or '').strip()
out_detail = (proc.stdout or '').strip()
combined = err_detail
if out_detail and out_detail not in err_detail:
combined = f'{err_detail}\n{out_detail}' if err_detail else out_detail
combined = combined or f'smartctl exited with code {proc.returncode}'
return jsonify({'error': f'Failed to start test: {combined}'}), 400
# Start background monitor to save JSON when test completes
sleep_interval = 10 if test_type == 'short' else 60

View File

@@ -901,7 +901,16 @@ TEMPLATES = {
},
'system_restore_completed': {
'title': '{hostname}: Host restore finished',
'body': 'Post-restore tasks completed in background.\n\nGuests applied: {guests}\nBind-mount stubs: {stubs}\nStale node dirs removed: {stale_nodes}\nComponents reinstalled: {components}\nDuration: {duration}\n\nThe node is now fully ready to use.',
'body': (
'Post-restore tasks completed in background.\n\n'
'Guests applied: {guests}\n'
'Bind-mount stubs: {stubs}\n'
'Stale node dirs removed: {stale_nodes}\n'
'Components reinstalled: {components}\n'
'Duration: {duration}\n'
'{warnings_block}\n'
'The node is now fully ready to use.'
),
'label': 'Host restore completed',
'group': 'services',
'default_enabled': True,