mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-04-05 20:03:48 +00:00
Update health monitor
This commit is contained in:
@@ -179,6 +179,66 @@ def get_full_health():
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@health_bp.route('/api/health/cleanup-orphans', methods=['POST'])
|
||||
def cleanup_orphan_errors():
|
||||
"""
|
||||
Clean up errors for devices that no longer exist in the system.
|
||||
Useful when USB drives or temporary devices are disconnected.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
try:
|
||||
cleaned = []
|
||||
# Get all active disk errors
|
||||
disk_errors = health_persistence.get_active_errors(category='disks')
|
||||
|
||||
for err in disk_errors:
|
||||
err_key = err.get('error_key', '')
|
||||
details = err.get('details', {})
|
||||
if isinstance(details, str):
|
||||
try:
|
||||
import json as _json
|
||||
details = _json.loads(details)
|
||||
except Exception:
|
||||
details = {}
|
||||
|
||||
device = details.get('device', '')
|
||||
base_disk = details.get('disk', '')
|
||||
|
||||
# Try to determine the device path
|
||||
dev_path = None
|
||||
if base_disk:
|
||||
dev_path = f'/dev/{base_disk}'
|
||||
elif device:
|
||||
dev_path = device if device.startswith('/dev/') else f'/dev/{device}'
|
||||
elif err_key.startswith('disk_'):
|
||||
# Extract device from error_key
|
||||
dev_name = err_key.replace('disk_fs_', '').replace('disk_', '')
|
||||
dev_name = re.sub(r'_.*$', '', dev_name) # Remove suffix
|
||||
if dev_name:
|
||||
dev_path = f'/dev/{dev_name}'
|
||||
|
||||
if dev_path:
|
||||
# Also check base disk (remove partition number)
|
||||
base_path = re.sub(r'\d+$', '', dev_path)
|
||||
if not os.path.exists(dev_path) and not os.path.exists(base_path):
|
||||
health_persistence.resolve_error(err_key, 'Device no longer present (manual cleanup)')
|
||||
cleaned.append({'error_key': err_key, 'device': dev_path})
|
||||
|
||||
# Also cleanup disk_observations for non-existent devices
|
||||
try:
|
||||
health_persistence.cleanup_orphan_observations()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return jsonify({
|
||||
'success': True,
|
||||
'cleaned_count': len(cleaned),
|
||||
'cleaned_errors': cleaned
|
||||
})
|
||||
except Exception as e:
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
@health_bp.route('/api/health/pending-notifications', methods=['GET'])
|
||||
def get_pending_notifications():
|
||||
"""
|
||||
|
||||
@@ -2093,7 +2093,21 @@ class HealthMonitor:
|
||||
# Check if the device still exists. If not, auto-resolve
|
||||
# the error -- it was likely a disconnected USB/temp device.
|
||||
dev_path = f'/dev/{base_disk}' if base_disk else device
|
||||
if not os.path.exists(dev_path):
|
||||
|
||||
# Also extract base disk from partition (e.g., sdb1 -> sdb)
|
||||
if not base_disk and device:
|
||||
# Remove /dev/ prefix and partition number
|
||||
dev_name = device.replace('/dev/', '')
|
||||
base_disk = re.sub(r'\d+$', '', dev_name) # sdb1 -> sdb
|
||||
if base_disk:
|
||||
dev_path = f'/dev/{base_disk}'
|
||||
|
||||
# Check both the specific device and the base disk
|
||||
device_exists = os.path.exists(dev_path)
|
||||
if not device_exists and device and device != dev_path:
|
||||
device_exists = os.path.exists(device)
|
||||
|
||||
if not device_exists:
|
||||
health_persistence.resolve_error(
|
||||
err_key, 'Device no longer present in system')
|
||||
continue
|
||||
|
||||
@@ -1765,6 +1765,47 @@ class HealthPersistence:
|
||||
except Exception as e:
|
||||
print(f"[HealthPersistence] Error marking removed disks: {e}")
|
||||
|
||||
def cleanup_orphan_observations(self):
|
||||
"""
|
||||
Dismiss observations for devices that no longer exist in /dev/.
|
||||
Useful for cleaning up after USB drives or temporary devices are disconnected.
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
try:
|
||||
conn = self._get_conn()
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Get all active (non-dismissed) observations
|
||||
cursor.execute('''
|
||||
SELECT id, device_name, serial FROM disk_observations
|
||||
WHERE dismissed = 0
|
||||
''')
|
||||
observations = cursor.fetchall()
|
||||
|
||||
dismissed_count = 0
|
||||
for obs_id, device_name, serial in observations:
|
||||
# Check if device exists
|
||||
dev_path = f'/dev/{device_name}'
|
||||
# Also check base device (remove partition number)
|
||||
base_dev = re.sub(r'\d+$', '', device_name)
|
||||
base_path = f'/dev/{base_dev}'
|
||||
|
||||
if not os.path.exists(dev_path) and not os.path.exists(base_path):
|
||||
cursor.execute('''
|
||||
UPDATE disk_observations SET dismissed = 1
|
||||
WHERE id = ?
|
||||
''', (obs_id,))
|
||||
dismissed_count += 1
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print(f"[HealthPersistence] Cleaned up {dismissed_count} orphan observations")
|
||||
return dismissed_count
|
||||
except Exception as e:
|
||||
print(f"[HealthPersistence] Error cleaning orphan observations: {e}")
|
||||
return 0
|
||||
|
||||
|
||||
# Global instance
|
||||
health_persistence = HealthPersistence()
|
||||
|
||||
Reference in New Issue
Block a user