From 14a1190dee9fce288ce7920b8bc4a04b1fa4cc90 Mon Sep 17 00:00:00 2001 From: Aleksei Fedorov Date: Mon, 1 Sep 2025 16:11:02 +0000 Subject: [PATCH] feat: implement nginx files visualization with Bezier curves - Add nginx files API endpoint to display open files - Integrate file names with decorative Bezier curves - Remove unnecessary documentation and backup files - Update .gitignore to exclude backup files - Position file labels at curve endpoints with proper styling --- .gitignore | 8 + DEPLOYMENT_SETUP.md | 108 ----------- PROJECT_STRUCTURE_GUIDE.md | 363 ------------------------------------- app.py.backup2 | 253 -------------------------- index.html | 2 +- static/js/main.js | 11 +- 6 files changed, 15 insertions(+), 730 deletions(-) delete mode 100644 DEPLOYMENT_SETUP.md delete mode 100755 PROJECT_STRUCTURE_GUIDE.md delete mode 100755 app.py.backup2 diff --git a/.gitignore b/.gitignore index f335fcc..71c0df9 100644 --- a/.gitignore +++ b/.gitignore @@ -191,3 +191,11 @@ docs/_build/ # PyBuilder target/ + +# Backup files +*.backup* +app.py.backup* + +# Documentation files (temporary) +DEPLOYMENT_SETUP.md +PROJECT_STRUCTURE_GUIDE.md diff --git a/DEPLOYMENT_SETUP.md b/DEPLOYMENT_SETUP.md deleted file mode 100644 index 29f34e5..0000000 --- a/DEPLOYMENT_SETUP.md +++ /dev/null @@ -1,108 +0,0 @@ -# Deployment Setup Guide - -## GitHub Repository Setup - -### 1. Add SSH Key to GitHub - -1. Copy the SSH public key from the server: -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "cat ~/.ssh/id_rsa.pub" -``` - -2. Go to your GitHub repository: https://github.com/devops-stack/ring-0/settings/keys - -3. Click "Add deploy key" - -4. Paste the SSH key and give it a name (e.g., "Ubuntu Server Deploy Key") - -5. Check "Allow write access" - -6. Click "Add key" - -### 2. GitHub Secrets Setup - -Add these secrets to your GitHub repository (Settings → Secrets and variables → Actions): - -- `HOST`: `3.70.234.196` -- `USERNAME`: `ubuntu` -- `SSH_KEY`: Your private SSH key (the content of `~/.ssh/webserver`) -- `PORT`: `22` - -### 3. Push Code to GitHub - -After adding the SSH key, run: -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "cd /opt/ring0/kernel-ai && git push -u origin main" -``` - -## Server Setup - -### 1. Enable Systemd Service - -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo systemctl enable kernel-ai" -``` - -### 2. Start the Service - -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo systemctl start kernel-ai" -``` - -### 3. Check Status - -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo systemctl status kernel-ai" -``` - -## Deployment Workflow - -### Manual Deployment - -Use the deployment script: -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "cd /opt/ring0/kernel-ai && ./deploy.sh" -``` - -Options: -- `./deploy.sh pull` - Pull latest code -- `./deploy.sh restart` - Restart services -- `./deploy.sh status` - Show service status -- `./deploy.sh logs` - Show recent logs -- `./deploy.sh deploy` - Full deployment (default) - -### Automatic Deployment - -Once GitHub Actions is configured, every push to the `main` branch will automatically deploy to the server. - -## Project Structure - -``` -/opt/ring0/kernel-ai/ -├── app.py # Flask backend -├── requirements.txt # Python dependencies -├── deploy.sh # Deployment script -├── .github/workflows/ # GitHub Actions -├── static/ # Static files (CSS, JS, images) -├── templates/ # HTML templates -├── docs/ # Documentation -├── tests/ # Test files -└── README.md # Project documentation -``` - -## Troubleshooting - -### Check Service Logs -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo journalctl -u kernel-ai -f" -``` - -### Check Nginx Logs -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo tail -f /var/log/nginx/error.log" -``` - -### Restart Everything -```bash -ssh -i ~/.ssh/webserver ubuntu@3.70.234.196 "sudo systemctl restart kernel-ai && sudo systemctl reload nginx" -``` diff --git a/PROJECT_STRUCTURE_GUIDE.md b/PROJECT_STRUCTURE_GUIDE.md deleted file mode 100755 index 9516600..0000000 --- a/PROJECT_STRUCTURE_GUIDE.md +++ /dev/null @@ -1,363 +0,0 @@ -# 📁 Project File Organization Guide - -## 🎯 Organization Principles - -### 1. **Separation of Concerns** -- **Backend** - server logic and API -- **Frontend** - user interface -- **Static Files** - CSS, JS, images -- **Templates** - HTML files - -### 2. **Modularity** -- Each component in separate file -- Reusable functions -- Clear interfaces between modules - -### 3. **Scalability** -- Easy to add new features -- Simple testing -- Clear structure for team - -## 📂 Standard Web Application Structure - -``` -project/ -├── app.py # Main application -├── requirements.txt # Python dependencies -├── README.md # Documentation -├── config.py # Configuration -├── static/ # Static files -│ ├── css/ # Styles -│ │ ├── main.css # Main styles -│ │ ├── components.css # Component styles -│ │ └── themes.css # Themes -│ ├── js/ # JavaScript -│ │ ├── main.js # Main logic -│ │ ├── modules/ # Modules -│ │ └── utils.js # Utilities -│ ├── images/ # Images -│ └── fonts/ # Fonts -├── templates/ # HTML templates -│ ├── base.html # Base template -│ ├── index.html # Main page -│ └── components/ # Components -├── api/ # API modules -│ ├── __init__.py -│ ├── routes.py # Routes -│ └── models.py # Data models -├── utils/ # Utilities -│ ├── __init__.py -│ └── helpers.py # Helper functions -├── tests/ # Tests -├── logs/ # Logs -└── docs/ # Documentation -``` - -## 🎨 CSS Organization - -### CSS File Structure: -```css -/* main.css - Main styles */ -/* 1. Reset and base styles */ -/* 2. Typography */ -/* 3. Layout and grid */ -/* 4. Components */ -/* 5. Utilities */ -/* 6. Media queries */ -``` - -### Organization Example: -```css -/* ===== RESET AND BASE STYLES ===== */ -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: 'Share Tech Mono', monospace; - background-color: #f2f2f2; -} - -/* ===== TYPOGRAPHY ===== */ -h1, h2, h3 { - font-weight: bold; -} - -/* ===== COMPONENTS ===== */ -.central-circle { - fill: rgba(0, 0, 0, 0.05); - stroke: #333; -} - -/* ===== UTILITIES ===== */ -.hidden { - display: none; -} - -/* ===== RESPONSIVENESS ===== */ -@media (max-width: 768px) { - /* Mobile styles */ -} -``` - -## 🔧 JavaScript Organization - -### JS File Structure: -```javascript -// main.js - Main logic -// 1. Initialization -// 2. Event handlers -// 3. Main functions -// 4. Utilities - -// modules/ - Modules -// - syscalls.js - System calls -// - visualization.js - Visualization -// - api.js - API work -``` - -### Module Example: -```javascript -// syscalls.js -class SyscallsManager { - constructor() { - this.data = []; - this.interval = null; - } - - // Class methods - async updateData() { /* ... */ } - render() { /* ... */ } - startAutoUpdate() { /* ... */ } -} - -// Export for use -if (typeof module !== 'undefined' && module.exports) { - module.exports = SyscallsManager; -} -``` - -## 🐍 Python (Flask) Organization - -### Application Structure: -```python -# app.py - Main application -from flask import Flask, jsonify, render_template -from api.routes import api_bp -from utils.helpers import get_system_info - -app = Flask(__name__) -app.register_blueprint(api_bp, url_prefix='/api') - -# Routes -@app.route('/') -def index(): - return render_template('index.html') - -# api/routes.py - API routes -from flask import Blueprint, jsonify - -api_bp = Blueprint('api', __name__) - -@api_bp.route('/syscalls-realtime') -def syscalls_realtime(): - return jsonify(get_syscalls_data()) -``` - -## 📋 Best Practices - -### 1. **File Naming** -- Use snake_case for Python -- Use kebab-case for HTML/CSS -- Use camelCase for JavaScript -- Make names descriptive - -### 2. **Comments** -```python -# Python -def get_system_calls(): - """ - Gets system calls in real-time. - - Returns: - list: List of system calls - """ - pass -``` - -```javascript -// JavaScript -/** - * Updates system calls data - * @param {number} interval - Update interval in ms - */ -function updateSyscalls(interval) { - // ... -} -``` - -```css -/* CSS */ -/* ===== SYSTEM CALLS ===== */ -.syscall-table { - /* System calls table styles */ -} -``` - -### 3. **Imports and Dependencies** -```python -# Python - group imports -# Standard library -import os -import sys -import json - -# Third-party libraries -from flask import Flask, jsonify -import psutil - -# Local modules -from utils.helpers import get_system_info -``` - -```javascript -// JavaScript - use ES6 modules -import { SyscallsManager } from './modules/syscalls.js'; -import { Visualization } from './modules/visualization.js'; -``` - -### 4. **Configuration** -```python -# config.py -class Config: - DEBUG = True - STATIC_FOLDER = 'static' - API_PREFIX = '/api' - -class ProductionConfig(Config): - DEBUG = False -``` - -## 🚀 Deployment - -### 1. **Production Structure** -``` -/var/www/your-app/ -├── app.py -├── static/ -├── templates/ -├── logs/ -└── venv/ -``` - -### 2. **Nginx Configuration** -```nginx -server { - listen 80; - server_name your-domain.com; - - root /var/www/your-app; - - location /static/ { - alias /var/www/your-app/static/; - expires 1y; - } - - location / { - proxy_pass http://127.0.0.1:5001; - } -} -``` - -### 3. **Systemd Service** -```ini -[Unit] -Description=Your Flask App -After=network.target - -[Service] -User=www-data -WorkingDirectory=/var/www/your-app -ExecStart=/var/www/your-app/venv/bin/python app.py -Restart=always - -[Install] -WantedBy=multi-user.target -``` - -## 📊 Monitoring and Logging - -### 1. **Log Structure** -``` -logs/ -├── app.log # Application logs -├── access.log # Access logs -├── error.log # Error logs -└── debug.log # Debug logs -``` - -### 2. **Logging Configuration** -```python -import logging -from logging.handlers import RotatingFileHandler - -# Logging setup -logging.basicConfig( - filename='logs/app.log', - level=logging.INFO, - format='%(asctime)s %(levelname)s: %(message)s' -) -``` - -## 🧪 Testing - -### 1. **Test Structure** -``` -tests/ -├── __init__.py -├── test_api.py # API tests -├── test_models.py # Model tests -└── test_utils.py # Utility tests -``` - -### 2. **Test Example** -```python -import unittest -from app import app - -class TestAPI(unittest.TestCase): - def setUp(self): - self.app = app.test_client() - - def test_syscalls_endpoint(self): - response = self.app.get('/api/syscalls-realtime') - self.assertEqual(response.status_code, 200) -``` - -## 📈 Scaling - -### 1. **Microservices** -``` -services/ -├── api-service/ # API service -├── web-service/ # Web interface -├── data-service/ # Data service -└── monitoring/ # Monitoring -``` - -### 2. **Docker** -```dockerfile -FROM python:3.9-slim -WORKDIR /app -COPY requirements.txt . -RUN pip install -r requirements.txt -COPY . . -EXPOSE 5001 -CMD ["python", "app.py"] -``` - ---- - -**Remember**: Good file organization makes projects more understandable, maintainable, and scalable! 🎯 diff --git a/app.py.backup2 b/app.py.backup2 deleted file mode 100755 index 36e9440..0000000 --- a/app.py.backup2 +++ /dev/null @@ -1,253 +0,0 @@ -#!/usr/bin/env python3 -""" -Linux Kernel Visualization Backend -Organized version with proper project structure -""" - -import os -import sys -import json -import time -import random -import platform -import subprocess -from datetime import datetime -from flask import Flask, jsonify, render_template, send_from_directory -import psutil - -# Try to import OpenAI (optional) -try: - import openai - OPENAI_AVAILABLE = True -except ImportError: - OPENAI_AVAILABLE = False - -app = Flask(__name__) - -# Configuration -class Config: - DEBUG = True - STATIC_FOLDER = 'static' - TEMPLATES_FOLDER = 'templates' - API_PREFIX = '/api' - -app.config.from_object(Config) - -def get_system_info(): - """Get system information""" - return { - 'platform': platform.system(), - 'kernel': platform.release(), - 'python_version': platform.python_version(), - 'cpu_count': psutil.cpu_count(), - 'memory_total': psutil.virtual_memory().total - } - -def get_real_system_calls(): - """Get real system calls""" - try: - # Try to get real data - if platform.system() == 'Linux': - # Read system entropy - try: - with open('/proc/sys/kernel/random/entropy_avail', 'r') as f: - entropy = int(f.read().strip()) - except: - entropy = random.randint(1000, 8000) - - # Generate realistic system calls - syscalls = [] - syscall_names = ['read', 'write', 'open', 'close', 'mmap', 'fork', 'execve', 'socket', 'connect', 'accept'] - - for _ in range(10): - name = random.choice(syscall_names) - count = f"{random.randint(100, 999)} {random.randint(100000, 999999)}" - syscalls.append({'name': name, 'count': count}) - - return syscalls - else: - # Fallback for other OS - return get_mock_system_calls() - except Exception as e: - print(f"Error getting system calls: {e}") - return get_mock_system_calls() - -def get_mock_system_calls(): - """Mock data for system calls""" - return [ - {'name': 'read', 'count': '166 643218'}, - {'name': 'write', 'count': '964 016161'}, - {'name': 'open', 'count': '972 983879'}, - {'name': 'close', 'count': '989 612075'}, - {'name': 'mmap', 'count': '819 540732'}, - {'name': 'fork', 'count': '512 826219'}, - {'name': 'execve', 'count': '025 461491'}, - {'name': 'socket', 'count': '838 475394'}, - {'name': 'connect', 'count': '632 094939'}, - {'name': 'accept', 'count': '417 205788'} - ] - -def get_kernel_subsystem_status(): - """Get kernel subsystem status""" - try: - if platform.system() == 'Linux': - subsystems = { - 'memory_management': { - 'status': 'active', - 'usage': random.randint(60, 95), - 'processes': random.randint(10, 50) - }, - 'process_scheduler': { - 'status': 'active', - 'usage': random.randint(70, 98), - 'processes': random.randint(20, 100) - }, - 'file_system': { - 'status': 'active', - 'usage': random.randint(40, 80), - 'processes': random.randint(5, 30) - }, - 'network_stack': { - 'status': 'active', - 'usage': random.randint(30, 70), - 'processes': random.randint(8, 25) - } - } - return subsystems - else: - return get_mock_kernel_subsystems() - except Exception as e: - print(f"Error getting subsystem status: {e}") - return get_mock_kernel_subsystems() - -def get_mock_kernel_subsystems(): - """Mock data for kernel subsystems""" - return { - 'memory_management': {'status': 'active', 'usage': 75, 'processes': 25}, - 'process_scheduler': {'status': 'active', 'usage': 85, 'processes': 45}, - 'file_system': {'status': 'active', 'usage': 60, 'processes': 15}, - 'network_stack': {'status': 'active', 'usage': 50, 'processes': 12} - } - -def get_process_kernel_map(): - """Get process to kernel subsystem mapping""" - try: - if not OPENAI_AVAILABLE: - return get_mock_process_kernel_map() - - # Try to use OpenAI API - if not hasattr(openai, 'api_key') or not openai.api_key: - return get_mock_process_kernel_map() - - # Here would be OpenAI API logic - # For now return mock data - return get_mock_process_kernel_map() - - except Exception as e: - print(f"Error getting process map: {e}") - return get_mock_process_kernel_map() - -def get_mock_process_kernel_map(): - """Mock data for process mapping""" - return { - "systemd": ["kernel/sched/core.c", "kernel/time/timekeeping.c"], - "sshd": ["kernel/security/security.c", "kernel/audit/audit.c"], - "nginx": ["kernel/net/socket.c", "kernel/net/core/sock.c"], - "python3": ["kernel/fs/read_write.c", "kernel/mm/memory.c"], - "bash": ["kernel/exec.c", "kernel/fork.c"], - "cron": ["kernel/time/timer.c", "kernel/sched/clock.c"] - } - -# API Endpoints - -@app.route('/') -def index(): - """Main page""" - return render_template('organized_index.html') - -@app.route('/api/syscalls-realtime') -def syscalls_realtime(): - """API for real-time system calls""" - try: - data = { - 'timestamp': datetime.now().isoformat(), - 'syscalls': get_real_system_calls(), - 'cpu_usage': psutil.cpu_percent(interval=1), - 'memory_usage': psutil.virtual_memory().percent, - 'system_info': get_system_info() - } - return jsonify(data) - except Exception as e: - return jsonify({'error': str(e)}), 500 - -@app.route('/api/kernel-data') -def kernel_data(): - """API for kernel data""" - try: - data = { - 'timestamp': datetime.now().isoformat(), - 'syscalls': get_real_system_calls(), - 'subsystems': get_kernel_subsystem_status(), - 'processes': len(psutil.pids()), - 'system_stats': { - 'cpu_count': psutil.cpu_count(), - 'memory_total': psutil.virtual_memory().total, - 'disk_usage': psutil.disk_usage('/').percent - } - } - return jsonify(data) - except Exception as e: - return jsonify({'error': str(e)}), 500 - -@app.route('/api/process-kernel-map') -def process_kernel_map(): - """API for process to kernel subsystem mapping""" - try: - data = get_process_kernel_map() - return jsonify(data) - except Exception as e: - return jsonify({'error': str(e)}), 500 - -@app.route('/health') -def health_check(): - """Application health check""" - return jsonify({ - 'status': 'healthy', - 'timestamp': datetime.now().isoformat(), - 'system_info': get_system_info() - }) - -# Static files handling -@app.route('/static/') -def static_files(filename): - """Serve static files""" - return send_from_directory(app.config['STATIC_FOLDER'], filename) - -# Error handling -@app.errorhandler(404) -def not_found(error): - return jsonify({'error': 'Not found'}), 404 - -@app.errorhandler(500) -def internal_error(error): - return jsonify({'error': 'Internal server error'}), 500 - -if __name__ == '__main__': - system_info = get_system_info() - - print("🚀 Linux Kernel Visualization Backend") - print(f"📍 Platform: {system_info['platform']}") - print(f"🐧 Kernel: {system_info['kernel']}") - print(f"🌐 Server: http://127.0.0.1:5001") - print(f"📊 API endpoints:") - print(f" - {Config.API_PREFIX}/syscalls-realtime") - print(f" - {Config.API_PREFIX}/kernel-data") - print(f" - {Config.API_PREFIX}/process-kernel-map") - print(f" - /health") - - app.run( - host='0.0.0.0', - port=5001, - debug=Config.DEBUG, - threaded=True - ) diff --git a/index.html b/index.html index 7a40692..a3d2684 100755 --- a/index.html +++ b/index.html @@ -25,6 +25,6 @@ - + diff --git a/static/js/main.js b/static/js/main.js index 0461587..84d2738 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -69,6 +69,7 @@ class NginxFilesManager { .attr("font-size", "11px") .attr("fill", "#222") .attr("opacity", 1) + .attr("transform", `rotate(90 ${pos.x} ${pos.y})`) .text(fileName); @@ -82,13 +83,13 @@ class NginxFilesManager { // Calculate positions for file labels calculateLabelPositions(numFiles, centerX, height) { const positions = []; - const baseY = height - 40; - const spacing = 120; + const baseY = height - 250; + const spacing = 40; for (let i = 0; i < numFiles; i++) { const offset = (i - (numFiles - 1) / 2) * spacing; positions.push({ - x: centerX + offset, + x: window.innerWidth - 150 + offset, y: baseY + (i % 2) * 15 }); } @@ -398,7 +399,7 @@ function drawLowerBezierGrid(num = 90) { window.nginxFilesManager.init(); } const height = window.innerHeight; - const yBase = height - 80; + const yBase = height - 200; for (let i = 0; i < num; i++) { const fromLeft = i < num / 2; @@ -414,7 +415,7 @@ function drawLowerBezierGrid(num = 90) { const controlY1 = yBase - 60 - Math.random() * 40; const controlX2 = endX + (Math.random() - 0.5) * 60; - const controlY2 = endY + 40 + Math.random() * 20; + const controlY2 = endY + 40 + Math.random() * 220; const path = `M${startX},${yBase} C${controlX1},${controlY1} ${controlX2},${controlY2} ${endX},${endY}`;