From 2ce87cdac0e56a79bfe682fd314be33ddafddc82 Mon Sep 17 00:00:00 2001 From: MacRimi Date: Wed, 15 Oct 2025 00:03:56 +0200 Subject: [PATCH] Update AppImage --- AppImage/components/storage-overview.tsx | 7 +- AppImage/scripts/flask_server.py | 109 ++++++----------------- 2 files changed, 30 insertions(+), 86 deletions(-) diff --git a/AppImage/components/storage-overview.tsx b/AppImage/components/storage-overview.tsx index fcd19a4..d85b32d 100644 --- a/AppImage/components/storage-overview.tsx +++ b/AppImage/components/storage-overview.tsx @@ -72,9 +72,6 @@ interface ProxmoxStorageData { } const formatStorage = (sizeInGB: number): string => { - if (sizeInGB <= 0) { - return "0 GB" - } if (sizeInGB < 1) { // Less than 1 GB, show in MB return `${(sizeInGB * 1024).toFixed(1)} MB` @@ -358,9 +355,7 @@ export function StorageOverview() { : 0 const usagePercent = - storageData.total > 0 && totalProxmoxUsed > 0 - ? ((totalProxmoxUsed / (storageData.total * 1024)) * 100).toFixed(2) - : "0.00" + storageData.total > 0 ? ((totalProxmoxUsed / (storageData.total * 1024)) * 100).toFixed(2) : "0.00" return (
diff --git a/AppImage/scripts/flask_server.py b/AppImage/scripts/flask_server.py index f6422a6..b0d51e4 100644 --- a/AppImage/scripts/flask_server.py +++ b/AppImage/scripts/flask_server.py @@ -529,9 +529,8 @@ def serve_images(filename): # Moved helper functions for system info up # def get_system_info(): ... (moved up) -# get_storage_info() function is OPTIMIZED to remove SMART data def get_storage_info(): - """Get storage and disk information - OPTIMIZED: Basic info only, no SMART data""" + """Get storage and disk information""" try: storage_data = { 'total': 0, @@ -568,9 +567,10 @@ def get_storage_info(): total_disk_size_bytes += disk_size_bytes - print(f"[v0] Getting basic info for {disk_name}...") - basic_info = get_basic_disk_info(disk_name) - print(f"[v0] Basic info for {disk_name}: {basic_info}") + # Get SMART data for this disk + print(f"[v0] Getting SMART data for {disk_name}...") + smart_data = get_smart_data(disk_name) + print(f"[v0] SMART data for {disk_name}: {smart_data}") disk_size_kb = disk_size_bytes / 1024 @@ -581,17 +581,29 @@ def get_storage_info(): physical_disks[disk_name] = { 'name': disk_name, - 'size': disk_size_kb, - 'size_formatted': size_str, + 'size': disk_size_kb, # In KB for formatMemory() in Storage Summary + 'size_formatted': size_str, # Added formatted size string for Storage section 'size_bytes': disk_size_bytes, - 'temperature': basic_info.get('temperature', 0), - 'health': basic_info.get('health', 'unknown'), - 'model': basic_info.get('model', 'Unknown'), - 'rotation_rate': basic_info.get('rotation_rate', 0), + 'temperature': smart_data.get('temperature', 0), + 'health': smart_data.get('health', 'unknown'), + 'power_on_hours': smart_data.get('power_on_hours', 0), + 'smart_status': smart_data.get('smart_status', 'unknown'), + 'model': smart_data.get('model', 'Unknown'), + 'serial': smart_data.get('serial', 'Unknown'), + 'reallocated_sectors': smart_data.get('reallocated_sectors', 0), + 'pending_sectors': smart_data.get('pending_sectors', 0), + 'crc_errors': smart_data.get('crc_errors', 0), + 'rotation_rate': smart_data.get('rotation_rate', 0), # Added + 'power_cycles': smart_data.get('power_cycles', 0), # Added + 'percentage_used': smart_data.get('percentage_used'), # Added + 'media_wearout_indicator': smart_data.get('media_wearout_indicator'), # Added + 'wear_leveling_count': smart_data.get('wear_leveling_count'), # Added + 'total_lbas_written': smart_data.get('total_lbas_written'), # Added + 'ssd_life_left': smart_data.get('ssd_life_left') # Added } storage_data['disk_count'] += 1 - health = basic_info.get('health', 'unknown').lower() + health = smart_data.get('health', 'unknown').lower() if health == 'healthy': storage_data['healthy_disks'] += 1 elif health == 'warning': @@ -692,57 +704,6 @@ def get_storage_info(): 'critical_disks': 0 } -# New function to get basic disk info quickly -def get_basic_disk_info(disk_name): - """Get basic disk info quickly without full SMART scan - OPTIMIZED""" - basic_info = { - 'temperature': 0, - 'health': 'unknown', - 'model': 'Unknown', - 'rotation_rate': 0, - } - - try: - # Only get basic info (-i) and health (-H), skip full attributes scan - cmd = ['smartctl', '-i', '-H', '-j', f'/dev/{disk_name}'] - - result = subprocess.run(cmd, capture_output=True, text=True, timeout=5) - - if result.returncode in [0, 4]: # 0 = success, 4 = some SMART values exceeded threshold - try: - data = json.loads(result.stdout) - - # Extract model - if 'model_name' in data: - basic_info['model'] = data['model_name'] - elif 'model_family' in data: - basic_info['model'] = data['model_family'] - - # Extract rotation rate - if 'rotation_rate' in data: - basic_info['rotation_rate'] = data['rotation_rate'] - - # Extract SMART status - if 'smart_status' in data and 'passed' in data['smart_status']: - basic_info['health'] = 'healthy' if data['smart_status']['passed'] else 'critical' - - # Extract temperature (quick check) - if 'temperature' in data and 'current' in data['temperature']: - basic_info['temperature'] = data['temperature']['current'] - elif 'nvme_smart_health_information_log' in data: - nvme_data = data['nvme_smart_health_information_log'] - if 'temperature' in nvme_data: - basic_info['temperature'] = nvme_data['temperature'] - - except json.JSONDecodeError: - pass - - except Exception as e: - print(f"[v0] Error getting basic disk info for {disk_name}: {e}") - - return basic_info - - def get_smart_data(disk_name): """Get SMART data for a specific disk - Enhanced with multiple device type attempts""" smart_data = { @@ -2057,7 +2018,7 @@ def get_detailed_gpu_info(gpu): if 'clients' in json_data: client_count = len(json_data['clients']) print(f"[v0] *** FOUND CLIENTS SECTION with {client_count} client(s) ***", flush=True) - for client_id, client_data in json_data['clients']: + for client_id, client_data in json_data['clients'].items(): client_name = client_data.get('name', 'Unknown') client_pid = client_data.get('pid', 'Unknown') print(f"[v0] - Client: {client_name} (PID: {client_pid})", flush=True) @@ -2563,7 +2524,7 @@ def get_detailed_gpu_info(gpu): mem_clock = clocks['GFX_MCLK'] if 'value' in mem_clock: detailed_info['clock_memory'] = f"{mem_clock['value']} MHz" - print(f"[v0] Memory Clock: {detailed_info['clock_memory']}", flush=True) + print(f"[v0] Memory Clock: {detailed_info['clock_memory']} MHz", flush=True) data_retrieved = True # Parse GPU activity (gpu_activity.GFX) @@ -3612,20 +3573,9 @@ def api_system(): @app.route('/api/storage', methods=['GET']) def api_storage(): - """Get storage information - OPTIMIZED: Basic info only""" + """Get storage information""" return jsonify(get_storage_info()) -@app.route('/api/storage/disk//details', methods=['GET']) -def api_disk_details(disk_name): - """Get detailed SMART data for a specific disk - loaded on demand""" - try: - print(f"[v0] Getting detailed SMART data for {disk_name}...") - smart_data = get_smart_data(disk_name) - return jsonify(smart_data) - except Exception as e: - print(f"[v0] Error getting disk details: {e}") - return jsonify({'error': str(e)}), 500 - @app.route('/api/proxmox-storage', methods=['GET']) def api_proxmox_storage(): """Get Proxmox storage information""" @@ -4510,8 +4460,7 @@ def api_info(): 'endpoints': [ '/api/system', '/api/system-info', - '/api/storage', - '/api/storage/disk//details', # Added endpoint for detailed disk SMART data + '/api/storage', '/api/proxmox-storage', '/api/network', '/api/vms', @@ -4785,6 +4734,6 @@ if __name__ == '__main__': cli.show_server_banner = lambda *x: None # Print only essential information - print("API endpoints available at: /api/system, /api/system-info, /api/storage, /api/storage/disk//details, /api/proxmox-storage, /api/network, /api/vms, /api/logs, /api/health, /api/hardware, /api/gpu//realtime, /api/prometheus") + print("API endpoints available at: /api/system, /api/system-info, /api/storage, /api/proxmox-storage, /api/network, /api/vms, /api/logs, /api/health, /api/hardware, /api/prometheus") app.run(host='0.0.0.0', port=8008, debug=False)