mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-05-02 12:26:23 +00:00
Update notification service
This commit is contained in:
@@ -2432,9 +2432,30 @@ def api_storage_summary():
|
|||||||
return jsonify(storage_data)
|
return jsonify(storage_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify({'error': str(e)}), 500
|
return jsonify({'error': str(e)}), 500
|
||||||
# END OF CHANGE FOR /api/storage/summary
|
# END OF CHANGE FOR /api/storage/summary
|
||||||
|
|
||||||
def get_interface_type(interface_name):
|
@app.route('/api/storage/observations', methods=['GET'])
|
||||||
|
@require_auth
|
||||||
|
def api_storage_observations():
|
||||||
|
"""Get disk observations (permanent error history) for a specific disk or all disks."""
|
||||||
|
try:
|
||||||
|
device = request.args.get('device', '')
|
||||||
|
serial = request.args.get('serial', '')
|
||||||
|
|
||||||
|
# Strip /dev/ prefix if present
|
||||||
|
if device.startswith('/dev/'):
|
||||||
|
device = device[5:]
|
||||||
|
|
||||||
|
observations = health_persistence.get_disk_observations(
|
||||||
|
device_name=device or None,
|
||||||
|
serial=serial or None
|
||||||
|
)
|
||||||
|
|
||||||
|
return jsonify({'observations': observations})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'observations': [], 'error': str(e)}), 500
|
||||||
|
|
||||||
|
def get_interface_type(interface_name):
|
||||||
"""Detect the type of network interface"""
|
"""Detect the type of network interface"""
|
||||||
try:
|
try:
|
||||||
# Skip loopback
|
# Skip loopback
|
||||||
@@ -6515,6 +6536,21 @@ def api_health():
|
|||||||
'version': '1.0.2'
|
'version': '1.0.2'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@app.route('/api/health/acknowledge', methods=['POST'])
|
||||||
|
@require_auth
|
||||||
|
def api_health_acknowledge():
|
||||||
|
"""Acknowledge/dismiss a health error by error_key."""
|
||||||
|
try:
|
||||||
|
data = request.get_json()
|
||||||
|
error_key = data.get('error_key', '')
|
||||||
|
if not error_key:
|
||||||
|
return jsonify({'error': 'error_key is required'}), 400
|
||||||
|
|
||||||
|
result = health_persistence.acknowledge_error(error_key)
|
||||||
|
return jsonify({'success': True, 'result': result})
|
||||||
|
except Exception as e:
|
||||||
|
return jsonify({'error': str(e)}), 500
|
||||||
|
|
||||||
@app.route('/api/prometheus', methods=['GET'])
|
@app.route('/api/prometheus', methods=['GET'])
|
||||||
@require_auth
|
@require_auth
|
||||||
def api_prometheus():
|
def api_prometheus():
|
||||||
|
|||||||
@@ -973,10 +973,10 @@ class HealthMonitor:
|
|||||||
zfs_error_key = f'zfs_pool_{real_pool}'
|
zfs_error_key = f'zfs_pool_{real_pool}'
|
||||||
zfs_reason = f'ZFS pool {real_pool}: {pool_info["reason"]}'
|
zfs_reason = f'ZFS pool {real_pool}: {pool_info["reason"]}'
|
||||||
try:
|
try:
|
||||||
if not health_persistence.is_error_active(zfs_error_key, category='zfs'):
|
if not health_persistence.is_error_active(zfs_error_key, category='disks'):
|
||||||
health_persistence.record_error(
|
health_persistence.record_error(
|
||||||
error_key=zfs_error_key,
|
error_key=zfs_error_key,
|
||||||
category='zfs',
|
category='disks',
|
||||||
severity=pool_info.get('status', 'WARNING'),
|
severity=pool_info.get('status', 'WARNING'),
|
||||||
reason=zfs_reason,
|
reason=zfs_reason,
|
||||||
details={
|
details={
|
||||||
@@ -1102,7 +1102,12 @@ class HealthMonitor:
|
|||||||
for sl in (issue.get('smart_lines') or [])[:3]:
|
for sl in (issue.get('smart_lines') or [])[:3]:
|
||||||
smart_details_parts.append(sl)
|
smart_details_parts.append(sl)
|
||||||
detail_text = '; '.join(smart_details_parts[:3]) if smart_details_parts else 'SMART warning in journal'
|
detail_text = '; '.join(smart_details_parts[:3]) if smart_details_parts else 'SMART warning in journal'
|
||||||
checks['smart_health'] = {'status': 'WARNING', 'detail': detail_text}
|
checks['smart_health'] = {
|
||||||
|
'status': 'WARNING',
|
||||||
|
'detail': detail_text,
|
||||||
|
'dismissable': True,
|
||||||
|
'error_key': 'smart_health_journal',
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
checks['smart_health'] = {'status': 'OK', 'detail': 'No SMART warnings in journal'}
|
checks['smart_health'] = {'status': 'OK', 'detail': 'No SMART warnings in journal'}
|
||||||
if self.capabilities.get('has_zfs') and 'zfs_pools' not in checks:
|
if self.capabilities.get('has_zfs') and 'zfs_pools' not in checks:
|
||||||
@@ -3907,6 +3912,8 @@ class HealthMonitor:
|
|||||||
'io_lines': unique_io[:5],
|
'io_lines': unique_io[:5],
|
||||||
'sample': sample_line,
|
'sample': sample_line,
|
||||||
'source': 'journal',
|
'source': 'journal',
|
||||||
|
'dismissable': True,
|
||||||
|
'error_key': f'smart_{disk_name}',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Record as disk observation for the permanent history
|
# Record as disk observation for the permanent history
|
||||||
|
|||||||
@@ -480,7 +480,8 @@ class HealthPersistence:
|
|||||||
('updates', 'pending_updates'), ('updates', 'kernel_pve'),
|
('updates', 'pending_updates'), ('updates', 'kernel_pve'),
|
||||||
('security', 'security_'),
|
('security', 'security_'),
|
||||||
('pve_services', 'pve_service_'), ('vms', 'vmct_'), ('vms', 'vm_'), ('vms', 'ct_'),
|
('pve_services', 'pve_service_'), ('vms', 'vmct_'), ('vms', 'vm_'), ('vms', 'ct_'),
|
||||||
('disks', 'disk_'), ('logs', 'log_'), ('network', 'net_'),
|
('disks', 'disk_'), ('disks', 'smart_'), ('disks', 'zfs_pool_'),
|
||||||
|
('logs', 'log_'), ('network', 'net_'),
|
||||||
('temperature', 'temp_')]:
|
('temperature', 'temp_')]:
|
||||||
if error_key == prefix or error_key.startswith(prefix):
|
if error_key == prefix or error_key.startswith(prefix):
|
||||||
category = cat
|
category = cat
|
||||||
|
|||||||
Reference in New Issue
Block a user