oscarwang2 commited on
Commit
c1a37ff
1 Parent(s): 889f571

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -47
app.py CHANGED
@@ -1,64 +1,167 @@
1
- from flask import Flask, request, jsonify
2
  import os
3
- import subprocess
4
  import tempfile
5
- import json
 
 
 
 
 
6
  import multiprocessing
7
 
8
- app = Flask(__name__)
 
 
9
 
10
- # Dictionary to store donated CPU information
11
- donated_cpus = {}
12
- total_donated_cpus = 0
13
 
14
- @app.route('/donate_cpu', methods=['POST'])
15
- def donate_cpu():
16
- global total_donated_cpus
17
- data = request.get_json()
18
- host = data['host']
19
- cpu_count = data['cpu_count']
20
- donated_cpus[host] = {"cpu_count": cpu_count, "usage": 0.0}
21
- total_donated_cpus += cpu_count
22
- return jsonify({"status": "success", "message": f"CPU donated by {host}"})
23
 
24
- @app.route('/update_cpu_usage', methods=['POST'])
25
- def update_cpu_usage():
26
- data = request.get_json()
27
- host = data['host']
28
- usage = data['usage']
29
- if host in donated_cpus:
30
- donated_cpus[host]['usage'] = usage
31
- return jsonify({"status": "success", "message": f"Updated CPU usage for {host}: {usage}%"})
32
- return jsonify({"status": "error", "message": "Host not found"}), 404
 
 
 
33
 
34
- @app.route('/execute_script', methods=['POST'])
35
- def execute_script():
 
36
  try:
37
- data = request.get_json()
38
- script_content = data['script_content']
39
 
40
- # Save the script to a temporary file
41
- script_file = tempfile.NamedTemporaryFile(delete=False, suffix='.py')
42
- script_file.write(script_content.encode())
43
- script_file.close()
44
 
45
- # Run the script using the donated CPUs
46
- cpu_count = total_donated_cpus or 1 # Default to 1 if no CPUs are donated
47
- result = subprocess.run(['python', script_file.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, timeout=60)
48
 
49
- os.remove(script_file.name)
50
- return jsonify({
51
- "stdout": result.stdout,
52
- "stderr": result.stderr,
53
- "returncode": result.returncode
54
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  except Exception as e:
56
- return jsonify({"error": str(e)}), 500
 
57
 
 
 
 
 
 
 
 
 
 
58
  @app.route('/cpu_info', methods=['GET'])
59
- def cpu_info():
60
- info = [{"host": host, "cpu_count": data['cpu_count'], "usage": data['usage']} for host, data in donated_cpus.items()]
61
- return jsonify({"cpu_info": info})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  if __name__ == "__main__":
64
- app.run(host='0.0.0.0', port=7860)
 
 
1
  import os
 
2
  import tempfile
3
+ import shutil
4
+ from zipfile import ZipFile
5
+ import logging
6
+ import psutil
7
+ import subprocess
8
+ from flask import Flask, request, jsonify, render_template, send_file
9
  import multiprocessing
10
 
11
+ # Configure logging
12
+ logging.basicConfig(level=logging.INFO)
13
+ logger = logging.getLogger(__name__)
14
 
15
+ # Initialize Flask app
16
+ app = Flask(__name__)
 
17
 
18
+ connected_cpus = {"localhost": {"cpu_count": psutil.cpu_count(logical=False), "usage": 0.0}}
 
 
 
 
 
 
 
 
19
 
20
+ # Define the target function for multiprocessing
21
+ def target_function(script_path, folder_path):
22
+ output_log = tempfile.TemporaryFile(mode='w+t')
23
+ try:
24
+ result = subprocess.run(['python', script_path], cwd=folder_path, stdout=output_log, stderr=subprocess.STDOUT)
25
+ output_log.seek(0)
26
+ log_output = output_log.read()
27
+ except Exception as e:
28
+ log_output = str(e)
29
+ finally:
30
+ output_log.close()
31
+ return log_output
32
 
33
+ # Endpoint to handle file uploads and script execution
34
+ @app.route('/upload', methods=['POST'])
35
+ def handle_upload():
36
  try:
37
+ if 'file' not in request.files or 'script_content' not in request.form:
38
+ return jsonify({"status": "error", "message": "File or script content not provided"}), 400
39
 
40
+ files = request.files.getlist('file')
41
+ script_content = request.form['script_content']
 
 
42
 
43
+ # Create a temporary directory to store uploaded files
44
+ temp_dir = tempfile.mkdtemp()
 
45
 
46
+ # Save the uploaded files to the temporary directory
47
+ folder_path = os.path.join(temp_dir, 'uploaded_folder')
48
+ os.makedirs(folder_path, exist_ok=True)
49
+ for file_obj in files:
50
+ file_path = os.path.join(folder_path, file_obj.filename)
51
+ file_obj.save(file_path)
52
+
53
+ # Save the script content to a file
54
+ script_path = os.path.join(folder_path, 'user_script.py')
55
+ with open(script_path, 'w') as script_file:
56
+ script_file.write(script_content)
57
+
58
+ # Run the script using multiprocessing
59
+ log_output = run_script(script_path, folder_path)
60
+
61
+ # Create a zip file of the entire folder
62
+ zip_path = os.path.join(temp_dir, 'output_folder.zip')
63
+ with ZipFile(zip_path, 'w') as zipf:
64
+ for root, _, files in os.walk(folder_path):
65
+ for file in files:
66
+ zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), folder_path))
67
+
68
+ return jsonify({"status": "success", "log_output": log_output, "download_url": f"/download/{os.path.basename(zip_path)}"})
69
+
70
  except Exception as e:
71
+ logger.error(f"Error in handle_upload: {e}")
72
+ return jsonify({"status": "error", "message": str(e)}), 500
73
 
74
+ @app.route('/download/<filename>')
75
+ def download_file(filename):
76
+ try:
77
+ return send_file(os.path.join(tempfile.gettempdir(), filename), as_attachment=True)
78
+ except Exception as e:
79
+ logger.error(f"Error in download_file: {e}")
80
+ return jsonify({"status": "error", "message": str(e)}), 500
81
+
82
+ # Endpoint to get connected CPUs information
83
  @app.route('/cpu_info', methods=['GET'])
84
+ def get_cpu_info():
85
+ try:
86
+ info = []
87
+ for host, data in connected_cpus.items():
88
+ info.append(f"{host}: {data['cpu_count']} CPUs, {data['usage']}% usage")
89
+ return jsonify({"status": "success", "cpu_info": "\n".join(info)})
90
+ except Exception as e:
91
+ logger.error(f"Error in get_cpu_info: {e}")
92
+ return jsonify({"status": "error", "message": str(e)}), 500
93
+
94
+ # Endpoint to execute commands
95
+ @app.route('/execute_command', methods=['POST'])
96
+ def execute_command():
97
+ try:
98
+ command = request.form['command']
99
+ if not command:
100
+ return jsonify({"status": "error", "message": "No command provided"}), 400
101
+
102
+ # Ensure commands are executed in a safe environment
103
+ allowed_commands = ['pip install']
104
+ if not any(command.startswith(cmd) for cmd in allowed_commands):
105
+ return jsonify({"status": "error", "message": "Command not allowed"}), 400
106
+
107
+ output_log = tempfile.TemporaryFile(mode='w+t')
108
+ try:
109
+ result = subprocess.run(command.split(), stdout=output_log, stderr=subprocess.STDOUT)
110
+ output_log.seek(0)
111
+ log_output = output_log.read()
112
+ except Exception as e:
113
+ log_output = str(e)
114
+ finally:
115
+ output_log.close()
116
+ return jsonify({"status": "success", "log_output": log_output})
117
+
118
+ except Exception as e:
119
+ logger.error(f"Error in execute_command: {e}")
120
+ return jsonify({"status": "error", "message": str(e)}), 500
121
+
122
+ # Endpoint to donate CPU resources
123
+ @app.route('/donate_cpu', methods=['POST'])
124
+ def donate_cpu():
125
+ try:
126
+ data = request.json
127
+ host = data['host']
128
+ cpu_count = data['cpu_count']
129
+ connected_cpus[host] = {"cpu_count": cpu_count, "usage": 0.0}
130
+ return jsonify({"status": "success", "message": f"CPU resources from {host} donated successfully."})
131
+ except Exception as e:
132
+ logger.error(f"Error in donate_cpu: {e}")
133
+ return jsonify({"status": "error", "message": str(e)}), 500
134
+
135
+ # Endpoint to update CPU usage
136
+ @app.route('/update_cpu_usage', methods=['POST'])
137
+ def update_cpu_usage():
138
+ try:
139
+ data = request.json
140
+ host = data['host']
141
+ usage = data['usage']
142
+ if host in connected_cpus:
143
+ connected_cpus[host]['usage'] = usage
144
+ return jsonify({"status": "success", "message": f"CPU usage from {host} updated successfully."})
145
+ else:
146
+ return jsonify({"status": "error", "message": f"Host {host} not found."}), 404
147
+ except Exception as e:
148
+ logger.error(f"Error in update_cpu_usage: {e}")
149
+ return jsonify({"status": "error", "message": str(e)}), 500
150
+
151
+ # Main interface
152
+ @app.route('/')
153
+ def index():
154
+ return render_template('index.html')
155
+
156
+ def run_script(script_path, folder_path):
157
+ # Collect all available CPUs including the local host CPU
158
+ total_cpus = sum(cpu['cpu_count'] for cpu in connected_cpus.values()) + 1
159
+
160
+ # Use multiprocessing to run the script
161
+ with multiprocessing.Pool(total_cpus) as pool:
162
+ log_outputs = pool.starmap(target_function, [(script_path, folder_path)] * total_cpus)
163
+
164
+ return '\n'.join(log_outputs)
165
 
166
  if __name__ == "__main__":
167
+ app.run(host='0.0.0.0', port=7860, threaded=True)