Update flask_server.py

This commit is contained in:
MacRimi
2025-09-29 00:00:01 +02:00
parent 3c33d5982c
commit b19bac679a

View File

@@ -29,7 +29,6 @@ def serve_dashboard():
if os.path.exists(index_file): if os.path.exists(index_file):
return send_file(index_file) return send_file(index_file)
else: else:
# Fallback to enhanced HTML page with PWA support
return ''' return '''
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -44,86 +43,381 @@ def serve_dashboard():
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.jpg"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.jpg">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.jpg"> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.jpg">
<style> <style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
margin: 0; padding: 40px; background: #0a0a0a;
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a1a 100%); color: #fff;
color: #fff; min-height: 100vh; min-height: 100vh;
} }
.container { max-width: 900px; margin: 0 auto; } .header {
.header { text-align: center; margin-bottom: 50px; } background: #111;
.logo { width: 80px; height: 80px; margin: 0 auto 20px; border-radius: 16px; } border-bottom: 1px solid #333;
.title { font-size: 2.5rem; font-weight: 700; margin: 0 0 10px; } padding: 1rem 2rem;
.subtitle { font-size: 1.2rem; color: #888; margin: 0; } position: sticky;
.api-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; } top: 0;
.api-card { z-index: 50;
background: linear-gradient(135deg, #1a1a1a 0%, #2a2a2a 100%); }
padding: 25px; border-radius: 12px; .header-content {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1200px;
margin: 0 auto;
}
.logo-section { display: flex; align-items: center; gap: 1rem; }
.logo { width: 40px; height: 40px; border-radius: 8px; }
.title { font-size: 1.25rem; font-weight: 600; }
.subtitle { font-size: 0.875rem; color: #888; }
.server-info { display: flex; align-items: center; gap: 0.5rem; color: #888; }
.status-section { display: flex; align-items: center; gap: 1rem; }
.status-badge {
background: rgba(16, 185, 129, 0.1);
color: #10b981;
border: 1px solid rgba(16, 185, 129, 0.2);
padding: 0.25rem 0.75rem;
border-radius: 1rem;
font-size: 0.875rem;
}
.btn {
background: transparent;
border: 1px solid #333; border: 1px solid #333;
transition: all 0.3s ease; color: #fff;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
cursor: pointer;
font-size: 0.875rem;
} }
.api-card:hover { transform: translateY(-2px); border-color: #4f46e5; } .btn:hover { background: #222; }
.api-card h3 { margin: 0 0 15px; color: #4f46e5; font-size: 1.3rem; } .container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
.api-card a { .tabs { margin-bottom: 2rem; }
color: #60a5fa; text-decoration: none; .tab-list {
font-family: 'Monaco', 'Menlo', monospace; display: grid;
font-size: 0.9rem; grid-template-columns: repeat(5, 1fr);
background: #111;
border: 1px solid #333;
border-radius: 0.5rem;
overflow: hidden;
} }
.api-card a:hover { color: #93c5fd; text-decoration: underline; } .tab {
.status { background: transparent;
display: inline-block; border: none;
background: #10b981; color: #888;
color: white; padding: 0.75rem 1rem;
padding: 4px 12px; cursor: pointer;
border-radius: 20px; transition: all 0.2s;
font-size: 0.8rem; }
.tab.active { background: #4f46e5; color: white; }
.tab:hover:not(.active) { background: #222; color: #fff; }
.metrics-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.metric-card {
background: #111;
border: 1px solid #333;
border-radius: 0.75rem;
padding: 1.5rem;
}
.metric-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 1rem;
}
.metric-title { color: #888; font-size: 0.875rem; }
.metric-value { font-size: 2rem; font-weight: 700; margin-bottom: 0.5rem; }
.progress-bar {
width: 100%;
height: 8px;
background: #333;
border-radius: 4px;
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill { height: 100%; background: #4f46e5; transition: width 0.3s; }
.metric-info { color: #888; font-size: 0.75rem; }
.charts-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 1.5rem;
margin-bottom: 2rem;
}
.chart-card {
background: #111;
border: 1px solid #333;
border-radius: 0.75rem;
padding: 1.5rem;
}
.chart-title {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
font-size: 1.125rem;
font-weight: 600; font-weight: 600;
margin-top: 20px; }
.chart-placeholder {
height: 200px;
background: #0a0a0a;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
color: #666;
}
.info-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 1.5rem;
}
.info-card {
background: #111;
border: 1px solid #333;
border-radius: 0.75rem;
padding: 1.5rem;
}
.info-title {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
font-size: 1.125rem;
font-weight: 600;
}
.info-item {
display: flex;
justify-content: space-between;
margin-bottom: 0.75rem;
}
.info-label { color: #888; }
.info-value { font-weight: 500; }
.badge {
padding: 0.25rem 0.5rem;
border-radius: 0.375rem;
font-size: 0.75rem;
font-weight: 500;
}
.badge-green { background: rgba(16, 185, 129, 0.1); color: #10b981; border: 1px solid rgba(16, 185, 129, 0.2); }
.badge-blue { background: rgba(59, 130, 246, 0.1); color: #3b82f6; border: 1px solid rgba(59, 130, 246, 0.2); }
.badge-yellow { background: rgba(245, 158, 11, 0.1); color: #f59e0b; border: 1px solid rgba(245, 158, 11, 0.2); }
.footer {
margin-top: 3rem;
padding-top: 1.5rem;
border-top: 1px solid #333;
text-align: center;
color: #666;
font-size: 0.875rem;
} }
</style> </style>
</head> </head>
<body> <body>
<header class="header">
<div class="header-content">
<div class="logo-section">
<img src="/images/proxmenux-logo.png" alt="ProxMenux Logo" class="logo">
<div>
<div class="title">ProxMenux Monitor</div>
<div class="subtitle">Proxmox System Dashboard</div>
</div>
<div class="server-info">
<span>📊</span>
<div>
<div>proxmox-01</div>
<div style="font-size: 0.75rem;">pve-node-01</div>
</div>
</div>
</div>
<div class="status-section">
<div class="status-badge">✅ Healthy</div>
<div style="color: #888; font-size: 0.875rem;">Uptime: 15d 7h 23m</div>
<button class="btn" onclick="location.reload()">🔄 Refresh</button>
<button class="btn">🌙 Theme</button>
<button class="btn">🌐 Translate</button>
</div>
</div>
</header>
<div class="container"> <div class="container">
<div class="header"> <div class="tabs">
<img src="/images/proxmenux-logo.png" alt="ProxMenux" class="logo"> <div class="tab-list">
<h1 class="title">ProxMenux Monitor</h1> <button class="tab active">Overview</button>
<p class="subtitle">Proxmox System Monitoring Dashboard</p> <button class="tab">Storage</button>
<div class="status">🟢 Server Running</div> <button class="tab">Network</button>
<button class="tab">Virtual Machines</button>
<button class="tab">System Logs</button>
</div> </div>
<div class="api-grid">
<div class="api-card">
<h3>📊 System Metrics</h3>
<a href="/api/system">/api/system</a>
<p>CPU, memory, temperature, and uptime information</p>
</div> </div>
<div class="api-card">
<h3>💾 Storage Info</h3> <div class="metrics-grid">
<a href="/api/storage">/api/storage</a> <div class="metric-card">
<p>Disk usage, health status, and storage metrics</p> <div class="metric-header">
<div class="metric-title">CPU Usage</div>
<span>🖥️</span>
</div> </div>
<div class="api-card"> <div class="metric-value">67.3%</div>
<h3>🌐 Network Stats</h3> <div class="progress-bar">
<a href="/api/network">/api/network</a> <div class="progress-fill" style="width: 67.3%"></div>
<p>Interface status, traffic, and network information</p>
</div> </div>
<div class="api-card"> <div class="metric-info">↓ 2.1% from last hour</div>
<h3>🖥️ Virtual Machines</h3>
<a href="/api/vms">/api/vms</a>
<p>VM status, resource usage, and management</p>
</div> </div>
<div class="api-card">
<h3>📝 System Logs</h3> <div class="metric-card">
<a href="/api/logs">/api/logs</a> <div class="metric-header">
<p>Recent system events and log entries</p> <div class="metric-title">Memory Usage</div>
<span>💾</span>
</div> </div>
<div class="api-card"> <div class="metric-value">15.8 GB</div>
<h3>❤️ Health Check</h3> <div class="progress-bar">
<a href="/api/health">/api/health</a> <div class="progress-fill" style="width: 49.4%"></div>
<p>Server status and health monitoring</p> </div>
<div class="metric-info">49.4% of 32 GB • ↑ 1.2 GB</div>
</div>
<div class="metric-card">
<div class="metric-header">
<div class="metric-title">Temperature</div>
<span>🌡️</span>
</div>
<div class="metric-value">52°C</div>
<div style="margin: 0.5rem 0;">
<span class="badge badge-green">Normal</span>
</div>
<div class="metric-info">Max: 78°C • Avg: 48°C</div>
</div>
<div class="metric-card">
<div class="metric-header">
<div class="metric-title">Active VMs</div>
<span>🖥️</span>
</div>
<div class="metric-value">12</div>
<div style="margin: 0.5rem 0; display: flex; flex-wrap: wrap; gap: 0.25rem;">
<span class="badge badge-green">8 Running</span>
<span class="badge badge-yellow">4 Stopped</span>
</div>
<div class="metric-info">Total: 16 VMs configured</div>
</div>
</div>
<div class="charts-grid">
<div class="chart-card">
<div class="chart-title">
<span>📈</span>
CPU Usage (24h)
</div>
<div class="chart-placeholder">
CPU Usage Chart<br>
<small style="color: #888;">Real-time data from /api/system</small>
</div>
</div>
<div class="chart-card">
<div class="chart-title">
<span>💾</span>
Memory Usage (24h)
</div>
<div class="chart-placeholder">
Memory Usage Chart<br>
<small style="color: #888;">Real-time data from /api/system</small>
</div> </div>
</div> </div>
</div> </div>
<div class="info-grid">
<div class="info-card">
<div class="info-title">
<span>🖥️</span>
System Information
</div>
<div class="info-item">
<span class="info-label">Hostname:</span>
<span class="info-value">proxmox-01</span>
</div>
<div class="info-item">
<span class="info-label">Version:</span>
<span class="info-value">PVE 8.1.3</span>
</div>
<div class="info-item">
<span class="info-label">Kernel:</span>
<span class="info-value">6.5.11-7-pve</span>
</div>
<div class="info-item">
<span class="info-label">Architecture:</span>
<span class="info-value">x86_64</span>
</div>
</div>
<div class="info-card">
<div class="info-title">
<span>👥</span>
Active Sessions
</div>
<div class="info-item">
<span class="info-label">Web Console:</span>
<span class="badge badge-green">3 active</span>
</div>
<div class="info-item">
<span class="info-label">SSH Sessions:</span>
<span class="badge badge-blue">1 active</span>
</div>
<div class="info-item">
<span class="info-label">API Calls:</span>
<span class="info-value">247/hour</span>
</div>
</div>
<div class="info-card">
<div class="info-title">
<span>⚡</span>
Power & Performance
</div>
<div class="info-item">
<span class="info-label">Power State:</span>
<span class="badge badge-green">Running</span>
</div>
<div class="info-item">
<span class="info-label">Load Average:</span>
<span class="info-value">1.23, 1.45, 1.67</span>
</div>
<div class="info-item">
<span class="info-label">Boot Time:</span>
<span class="info-value">2.3s</span>
</div>
</div>
</div>
<div class="footer">
<p>Last updated: <span id="timestamp"></span> • ProxMenux Monitor v1.0.0</p>
</div>
</div>
<script> <script>
// Update timestamp
document.getElementById('timestamp').textContent = new Date().toLocaleTimeString();
// Tab functionality
document.querySelectorAll('.tab').forEach(tab => {
tab.addEventListener('click', function() {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
this.classList.add('active');
});
});
// Auto-refresh data every 30 seconds
setInterval(() => {
fetch('/api/system')
.then(response => response.json())
.then(data => {
// Update metrics with real data
console.log('Updated system data:', data);
document.getElementById('timestamp').textContent = new Date().toLocaleTimeString();
})
.catch(error => console.log('Error fetching data:', error));
}, 30000);
// PWA Service Worker Registration // PWA Service Worker Registration
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js'); navigator.serviceWorker.register('/sw.js');