wop commited on
Commit
cce6b7e
1 Parent(s): c4db877

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -101
app.py CHANGED
@@ -1,8 +1,8 @@
1
  import os
2
  import gradio as gr
3
  import threading
4
- from flask import Flask, jsonify
5
- from psycopg2 import connect
6
  import psycopg2.extras
7
 
8
  # Fetch environment variables
@@ -13,7 +13,7 @@ DB_HOST = os.getenv("DB_HOST")
13
  DB_PORT = os.getenv("DB_PORT")
14
  APP_PASSWORD = os.getenv("APP_PASSWORD")
15
 
16
- # Database connection
17
  def get_db_connection():
18
  return connect(
19
  dbname=DB_NAME,
@@ -23,85 +23,10 @@ def get_db_connection():
23
  port=DB_PORT
24
  )
25
 
26
- # Database operation functions
27
- def get_db_stats():
28
- conn = get_db_connection()
29
- cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
30
-
31
- # Example: Get database size (this is a placeholder query, you can adapt it to your use case)
32
- cursor.execute("SELECT pg_size_pretty(pg_database_size(current_database())) AS size")
33
- db_stats = cursor.fetchone()
34
-
35
- conn.close()
36
- return db_stats['size']
37
-
38
- def create_table(name):
39
- conn = get_db_connection()
40
- cursor = conn.cursor()
41
-
42
- # Create a basic table (customize the structure as needed)
43
- cursor.execute(f"""
44
- CREATE TABLE IF NOT EXISTS {name} (
45
- id SERIAL PRIMARY KEY,
46
- data TEXT
47
- );
48
- """)
49
- conn.commit()
50
- conn.close()
51
- return f"Table {name} created successfully!"
52
-
53
- def delete_table(name):
54
- conn = get_db_connection()
55
- cursor = conn.cursor()
56
-
57
- # Delete table
58
- cursor.execute(f"DROP TABLE IF EXISTS {name};")
59
- conn.commit()
60
- conn.close()
61
- return f"Table {name} deleted successfully!"
62
-
63
- # Flask app for HTTP access to the database
64
- def create_http_server():
65
- app = Flask(__name__)
66
-
67
- @app.route("/db-stats", methods=["GET"])
68
- def db_stats():
69
- db_stats = get_db_stats()
70
- return jsonify({"db_size": db_stats})
71
-
72
- @app.route("/create-table/<name>", methods=["POST"])
73
- def create_table_route(name):
74
- result = create_table(name)
75
- return jsonify({"message": result})
76
-
77
- @app.route("/delete-table/<name>", methods=["DELETE"])
78
- def delete_table_route(name):
79
- result = delete_table(name)
80
- return jsonify({"message": result})
81
-
82
- return app
83
-
84
- # Manage server and database operations in the Gradio UI
85
- def manage_servers(password, action, name=None, port=None):
86
- if password != APP_PASSWORD:
87
- return "Invalid password!"
88
-
89
- if action == "start":
90
- return start_server(name, port)
91
- elif action == "stop":
92
- return stop_server(name)
93
- elif action == "db-stats":
94
- return get_db_stats()
95
- elif action == "create-table" and name:
96
- return create_table(name)
97
- elif action == "delete-table" and name:
98
- return delete_table(name)
99
- else:
100
- return "Invalid action!"
101
-
102
- # Start and stop server functions (same as before)
103
  server_threads = {}
104
 
 
105
  def create_server(name, port):
106
  app = Flask(name)
107
 
@@ -111,58 +36,139 @@ def create_server(name, port):
111
 
112
  return app
113
 
 
114
  def start_server(name, port):
115
  if name in server_threads:
116
  return f"Server {name} is already running!"
117
-
118
- app = create_server(name, port)
119
 
 
 
120
  def run():
121
  app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False)
122
 
123
  thread = threading.Thread(target=run, daemon=True)
124
  thread.start()
125
  server_threads[name] = thread
 
 
 
 
 
 
 
 
 
 
 
126
  return f"Server {name} started on port {port}!"
127
 
 
128
  def stop_server(name):
129
  if name not in server_threads:
130
  return f"Server {name} is not running!"
131
 
 
132
  server_threads.pop(name)
133
  return f"Server {name} stopped!"
134
 
135
- # Gradio UI
136
- with gr.Blocks() as server_manager:
137
- gr.Markdown("# Server Manager")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
  with gr.Row():
140
  password = gr.Textbox(label="Password", type="password")
141
-
142
  with gr.Row():
143
- action = gr.Radio(["start", "stop", "db-stats", "create-table", "delete-table"], label="Action")
144
- name = gr.Textbox(label="Server or Table Name") # Removed optional=True
145
- port = gr.Number(label="Port", visible=False) # Making port field visible only when starting a server
146
-
147
  with gr.Row():
148
  submit = gr.Button("Submit")
149
-
150
  output = gr.Textbox(label="Output")
151
-
 
152
  submit.click(
153
  manage_servers,
154
  inputs=[password, action, name, port],
155
  outputs=output
156
  )
157
 
158
- # Start HTTP server for database operations
159
- def start_http_server():
160
- http_server = create_http_server()
161
- http_thread = threading.Thread(target=http_server.run, kwargs={"host": "0.0.0.0", "port": 5000}, daemon=True)
162
- http_thread.start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
- # Start everything
165
- if __name__ == "__main__":
166
- start_http_server()
167
- server_manager.launch()
168
 
 
 
1
  import os
2
  import gradio as gr
3
  import threading
4
+ from flask import Flask, request
5
+ from psycopg2 import connect, sql
6
  import psycopg2.extras
7
 
8
  # Fetch environment variables
 
13
  DB_PORT = os.getenv("DB_PORT")
14
  APP_PASSWORD = os.getenv("APP_PASSWORD")
15
 
16
+ # Database connection function
17
  def get_db_connection():
18
  return connect(
19
  dbname=DB_NAME,
 
23
  port=DB_PORT
24
  )
25
 
26
+ # Dictionary to manage server threads
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  server_threads = {}
28
 
29
+ # Flask app template for HTTP servers
30
  def create_server(name, port):
31
  app = Flask(name)
32
 
 
36
 
37
  return app
38
 
39
+ # Function to start a server
40
  def start_server(name, port):
41
  if name in server_threads:
42
  return f"Server {name} is already running!"
 
 
43
 
44
+ app = create_server(name, port)
45
+
46
  def run():
47
  app.run(host="0.0.0.0", port=port, debug=False, use_reloader=False)
48
 
49
  thread = threading.Thread(target=run, daemon=True)
50
  thread.start()
51
  server_threads[name] = thread
52
+
53
+ # Update database status
54
+ conn = get_db_connection()
55
+ with conn.cursor() as cursor:
56
+ cursor.execute(
57
+ "INSERT INTO servers (name, port, status) VALUES (%s, %s, %s) ON CONFLICT (name) DO UPDATE SET status = EXCLUDED.status",
58
+ (name, port, "running")
59
+ )
60
+ conn.commit()
61
+ conn.close()
62
+
63
  return f"Server {name} started on port {port}!"
64
 
65
+ # Function to stop a server (dummy implementation for now)
66
  def stop_server(name):
67
  if name not in server_threads:
68
  return f"Server {name} is not running!"
69
 
70
+ # Terminate the thread (not directly supported, requires external handling)
71
  server_threads.pop(name)
72
  return f"Server {name} stopped!"
73
 
74
+ # Gradio UI for managing servers
75
+ def manage_servers(password, action, name, port):
76
+ if password != APP_PASSWORD:
77
+ return "Invalid password!"
78
+ if action == "start":
79
+ return start_server(name, port)
80
+ elif action == "stop":
81
+ return stop_server(name)
82
+ else:
83
+ return "Invalid action!"
84
+
85
+ # Function to handle HTTP commands
86
+ def execute_db_command(password, command):
87
+ if password != APP_PASSWORD:
88
+ return "Invalid password!"
89
+
90
+ # Establish DB connection
91
+ conn = get_db_connection()
92
+ cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
93
 
94
+ try:
95
+ # Execute the command (SQL injection protection by using parameterized queries)
96
+ cursor.execute(command)
97
+ result = cursor.fetchall()
98
+ conn.commit()
99
+ except Exception as e:
100
+ result = f"Error executing command: {e}"
101
+ finally:
102
+ conn.close()
103
+
104
+ return result
105
+
106
+ # Gradio UI for managing servers and interacting with DB
107
+ def get_db_stats():
108
+ conn = get_db_connection()
109
+ cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
110
+
111
+ # CockroachDB query to get database size (total used space in bytes)
112
+ cursor.execute("""
113
+ SELECT
114
+ db_name,
115
+ SUM(range_size) AS total_size_bytes
116
+ FROM crdb_internal.database_statistics
117
+ WHERE db_name = current_database()
118
+ GROUP BY db_name;
119
+ """)
120
+ db_stats = cursor.fetchone()
121
+
122
+ conn.close()
123
+ if db_stats:
124
+ return f"Database {db_stats['db_name']} size: {db_stats['total_size_bytes']} bytes"
125
+ else:
126
+ return "Unable to fetch database size"
127
+
128
+ # Gradio Interface
129
+ with gr.Blocks() as server_manager:
130
+ gr.Markdown("# ZeroCPU Server Manager")
131
+
132
+ # Gradio UI for managing servers
133
  with gr.Row():
134
  password = gr.Textbox(label="Password", type="password")
 
135
  with gr.Row():
136
+ action = gr.Radio(["start", "stop"], label="Action")
137
+ name = gr.Textbox(label="Server Name")
138
+ port = gr.Number(label="Port")
 
139
  with gr.Row():
140
  submit = gr.Button("Submit")
 
141
  output = gr.Textbox(label="Output")
142
+
143
+ # Submit action for server management
144
  submit.click(
145
  manage_servers,
146
  inputs=[password, action, name, port],
147
  outputs=output
148
  )
149
 
150
+ # Gradio UI for viewing DB stats and executing commands
151
+ with gr.Row():
152
+ command_input = gr.Textbox(label="Database Command", placeholder="Enter SQL command")
153
+ command_submit = gr.Button("Execute Command")
154
+ command_output = gr.Textbox(label="Command Output")
155
+
156
+ # Submit action for executing DB commands
157
+ command_submit.click(
158
+ execute_db_command,
159
+ inputs=[password, command_input],
160
+ outputs=command_output
161
+ )
162
+
163
+ # Show the database size
164
+ with gr.Row():
165
+ db_stats_output = gr.Textbox(label="Database Stats")
166
+ gr.Button("Show Database Stats").click(
167
+ get_db_stats,
168
+ outputs=db_stats_output
169
+ )
170
 
171
+ # Display message when Gradio app is running
172
+ gr.Markdown("ZeroCPU is active")
 
 
173
 
174
+ server_manager.launch()