# app/web/routes.py from flask import Blueprint, render_template, current_app bp = Blueprint('web', __name__, url_prefix='/app', template_folder='../templates') @bp.route('/', methods=['GET']) def index(): # Fetch all nodes with latest stats query = """ SELECT na.node_name, na.status, ni.hostname, cu.cpu_percent, mu.memory_percent, du.disk_percent, ni.last_updated FROM node_auth na LEFT JOIN node_info ni ON na.node_id = ni.node_id LEFT JOIN ( SELECT node_id, cpu_percent FROM cpu_usage WHERE timestamp = (SELECT MAX(timestamp) FROM cpu_usage cu2 WHERE cu2.node_id = cpu_usage.node_id) ) cu ON na.node_id = cu.node_id LEFT JOIN ( SELECT node_id, memory_percent FROM memory_usage WHERE timestamp = (SELECT MAX(timestamp) FROM memory_usage mu2 WHERE mu2.node_id = memory_usage.node_id) ) mu ON na.node_id = mu.node_id LEFT JOIN ( SELECT node_id, disk_percent FROM disk_usage WHERE timestamp = (SELECT MAX(timestamp) FROM disk_usage du2 WHERE du2.node_id = disk_usage.node_id) ) du ON na.node_id = du.node_id ORDER BY na.node_name """ result = current_app.db.execute_read_sync(query) nodes = [] if result.success and result.data: for row in result.data: node = { 'node_name': row[0], 'status': row[1], 'hostname': row[2], 'cpu_percent': row[3], 'memory_percent': row[4], 'disk_percent': row[5], 'last_updated': row[6], 'connections': [] } # Fetch connections conn_query = """ SELECT na2.node_name, na2.status, nc.ping_latency_ms FROM node_connections nc JOIN node_auth na2 ON nc.target_node_id = na2.node_id WHERE nc.source_node_id = (SELECT node_id FROM node_auth WHERE node_name = ?) AND nc.timestamp = (SELECT MAX(timestamp) FROM node_connections nc2 WHERE nc2.source_node_id = nc.source_node_id AND nc2.target_node_id = nc.target_node_id) """ conn_result = current_app.db.execute_read_sync(conn_query, (node['node_name'],)) if conn_result.success and conn_result.data: node['connections'] = [{'target_node_name': r[0], 'target_status': r[1], 'ping_latency_ms': r[2]} for r in conn_result.data] nodes.append(node) return render_template('index.html', nodes=nodes) @bp.route('/node/', methods=['GET']) def node_detail(node_name): # Fetch latest node info query = """ SELECT na.node_name, na.status, ni.hostname, ni.ip_address, ni.os_type, cu.cpu_percent, mu.memory_percent, du.disk_percent, ni.last_updated FROM node_auth na LEFT JOIN node_info ni ON na.node_id = ni.node_id LEFT JOIN ( SELECT node_id, cpu_percent FROM cpu_usage WHERE timestamp = (SELECT MAX(timestamp) FROM cpu_usage cu2 WHERE cu2.node_id = cpu_usage.node_id) ) cu ON na.node_id = cu.node_id LEFT JOIN ( SELECT node_id, memory_percent FROM memory_usage WHERE timestamp = (SELECT MAX(timestamp) FROM memory_usage mu2 WHERE mu2.node_id = memory_usage.node_id) ) mu ON na.node_id = mu.node_id LEFT JOIN ( SELECT node_id, disk_percent FROM disk_usage WHERE timestamp = (SELECT MAX(timestamp) FROM disk_usage du2 WHERE du2.node_id = disk_usage.node_id) ) du ON na.node_id = du.node_id WHERE na.node_name = ? """ result = current_app.db.execute_read_sync(query, (node_name,)) if not result.success or not result.data: return "Node not found", 404 node = { 'node_name': result.data[0][0], 'status': result.data[0][1], 'hostname': result.data[0][2], 'ip_address': result.data[0][3], 'os_type': result.data[0][4], 'cpu_percent': result.data[0][5], 'memory_percent': result.data[0][6], 'disk_percent': result.data[0][7], 'last_updated': result.data[0][8] } # Fetch historical data (last 50 entries) history_query = """ SELECT timestamp, cpu_percent FROM cpu_usage WHERE node_id = (SELECT node_id FROM node_auth WHERE node_name = ?) ORDER BY timestamp DESC LIMIT 50 """ cpu_result = current_app.db.execute_read_sync(history_query, (node_name,)) history_timestamps = [r[0].split('T')[1][:5] for r in cpu_result.data] if cpu_result.success and cpu_result.data else [] history_cpu = [r[1] for r in cpu_result.data] if cpu_result.success and cpu_result.data else [] memory_query = """ SELECT memory_percent FROM memory_usage WHERE node_id = (SELECT node_id FROM node_auth WHERE node_name = ?) ORDER BY timestamp DESC LIMIT 50 """ memory_result = current_app.db.execute_read_sync(memory_query, (node_name,)) history_memory = [r[0] for r in memory_result.data] if memory_result.success and memory_result.data else [] disk_query = """ SELECT disk_percent FROM disk_usage WHERE node_id = (SELECT node_id FROM node_auth WHERE node_name = ?) ORDER BY timestamp DESC LIMIT 50 """ disk_result = current_app.db.execute_read_sync(disk_query, (node_name,)) history_disk = [r[0] for r in disk_result.data] if disk_result.success and disk_result.data else [] return render_template( 'node_detail.html', node_name=node_name, node=node, history_timestamps=history_timestamps[::-1], # Reverse for chronological order history_cpu=history_cpu[::-1], history_memory=history_memory[::-1], history_disk=history_disk[::-1] )