import os import time import uuid import psutil import subprocess import pymysql from flask import Flask, jsonify, request, abort, render_template_string app = Flask(__name__) MYSQL_CONFIG = { "host": os.getenv("MYSQL_HOST", "localhost"), "port": int(os.getenv("MYSQL_PORT", 3306)), "user": os.getenv("MYSQL_USER", "root"), "password": os.getenv("MYSQL_PASSWORD", "password"), } MIN_DB_MB = 500 MAX_DB_MB = 5000 TOTAL_MAX_MB = 25000 start_time = time.time() db_registry = {} def ensure_mysql_running(): try: conn = pymysql.connect( host=MYSQL_CONFIG["host"], port=MYSQL_CONFIG["port"], user=MYSQL_CONFIG["user"], password=MYSQL_CONFIG["password"] ) conn.close() except Exception: try: subprocess.Popen(["mysqld_safe"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) time.sleep(5) except Exception: try: subprocess.Popen(["service", "mysql", "start"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) time.sleep(5) except Exception: pass ensure_mysql_running() DASHBOARD_TEMPLATE = """ MySQL DB Manager Dashboard

MySQL DB Manager Dashboard

System & Storage

Uptime: {{ uptime_seconds }} seconds

CPU usage: {{ system_stats.cpu.usage_percent }}% (cores: {{ system_stats.cpu.cores_detected }})

RAM usage: {{ '%.2f' % system_stats.ram.used_gb }} GB / {{ '%.2f' % system_stats.ram.total_gb }} GB ({{ system_stats.ram.usage_percent }}%)

Disk usage: {{ '%.2f' % system_stats.disk.used_gb }} GB / {{ '%.2f' % system_stats.disk.total_gb }} GB ({{ system_stats.disk.usage_percent }}%)

DB Allocated Size: {{ total_allocated_mb }} MB / {{ total_max_mb }} MB

Create New Database

This reserves capacity; size is not strictly enforced by MySQL itself.

Existing Databases

{% if dbs %} {% for db in dbs %} {% endfor %}
UUID DB Name Allocated Size (MB) Created At (unix) Example Query Endpoint
{{ db.uuid }} {{ db.name }} {{ db.size_mb }} {{ db.created_at }} /api/{{ db.uuid }}/query
{% else %}

No databases created yet.

{% endif %}

API Reference

""" def get_mysql_connection(database=None): cfg = MYSQL_CONFIG.copy() if database: cfg["database"] = database return pymysql.connect( host=cfg["host"], port=cfg["port"], user=cfg["user"], password=cfg["password"], database=cfg.get("database"), autocommit=False, cursorclass=pymysql.cursors.DictCursor, ) def get_system_stats(): cpu_percent = psutil.cpu_percent(interval=0.1) cpu_count = psutil.cpu_count(logical=False) or psutil.cpu_count() vm = psutil.virtual_memory() ram_total_gb = vm.total / (1024**3) ram_used_gb = (vm.total - vm.available) / (1024**3) ram_percent = vm.percent disk = psutil.disk_usage("/") disk_total_gb = disk.total / (1024**3) disk_used_gb = disk.used / (1024**3) disk_percent = disk.percent return { "cpu": {"usage_percent": cpu_percent, "cores_detected": cpu_count}, "ram": {"total_gb": ram_total_gb, "used_gb": ram_used_gb, "usage_percent": ram_percent}, "disk": {"total_gb": disk_total_gb, "used_gb": disk_used_gb, "usage_percent": disk_percent}, } def total_allocated_mb(): return sum(db["size_mb"] for db in db_registry.values()) @app.route("/") def dashboard(): system_stats = get_system_stats() uptime_seconds = int(time.time() - start_time) dbs = [{"uuid": k, "name": v["db_name"], "size_mb": v["size_mb"], "created_at": int(v["created_at"])} for k, v in db_registry.items()] return render_template_string( DASHBOARD_TEMPLATE, system_stats=system_stats, uptime_seconds=uptime_seconds, total_allocated_mb=total_allocated_mb(), total_max_mb=TOTAL_MAX_MB, min_db_mb=MIN_DB_MB, max_db_mb=MAX_DB_MB, dbs=dbs, ) @app.route("/health") def health(): uptime_seconds = int(time.time() - start_time) try: conn = get_mysql_connection() cur = conn.cursor() cur.execute("SELECT 1") cur.fetchone() cur.close() conn.close() db_status = "ok" except Exception as e: db_status = f"error: {e}" return jsonify({ "status": "ok", "uptime_seconds": uptime_seconds, "db_status": db_status, "total_allocated_mb": total_allocated_mb(), "total_max_mb": TOTAL_MAX_MB, }) @app.route("/api/db", methods=["POST"]) def create_db(): data = request.get_json(silent=True) or {} size_mb = data.get("size_mb") if not isinstance(size_mb, (int, float)): return jsonify({"error": "size_mb must be a number"}), 400 size_mb = int(size_mb) if size_mb < MIN_DB_MB or size_mb > MAX_DB_MB: return jsonify({"error": f"size_mb must be between {MIN_DB_MB} and {MAX_DB_MB} MB"}), 400 if total_allocated_mb() + size_mb > TOTAL_MAX_MB: return jsonify({"error": "Total allocated size would exceed 25GB limit"}), 400 db_uuid = str(uuid.uuid4()) db_name = f"db_{db_uuid.replace('-', '')[:16]}" try: conn = get_mysql_connection() conn.autocommit(True) cur = conn.cursor() cur.execute(f"CREATE DATABASE `{db_name}`") cur.close() conn.close() except Exception as e: ensure_mysql_running() try: conn = get_mysql_connection() conn.autocommit(True) cur = conn.cursor() cur.execute(f"CREATE DATABASE `{db_name}`") cur.close() conn.close() except Exception as e2: return jsonify({"error": f"Failed to create database: {e2}"}), 500 db_registry[db_uuid] = {"db_name": db_name, "size_mb": size_mb, "created_at": time.time()} return jsonify({"uuid": db_uuid, "db_name": db_name, "size_mb": size_mb, "query_endpoint": f"/api/{db_uuid}/query"}) @app.route("/api//query", methods=["POST"]) def db_query(db_uuid): if db_uuid not in db_registry: abort(404, description="Unknown database UUID") data = request.get_json(silent=True) or {} query = data.get("query") if not query: return jsonify({"status": "error", "error": "Missing 'query' in JSON body"}), 400 db_name = db_registry[db_uuid]["db_name"] try: conn = get_mysql_connection(database=db_name) cur = conn.cursor() cur.execute(query) rows = cur.fetchall() if cur.description else None try: conn.commit() except Exception: conn.rollback() cur.close() conn.close() return jsonify({"status": "ok", "rows": rows}) except Exception as e: return jsonify({"status": "error", "error": str(e)}), 500 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)