| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | # module has yet to be made capable of running in multiple processes | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | import os | 
					
						
							|  |  |  | import logging | 
					
						
							|  |  |  | import threading | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | import typing | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | import multiprocessing | 
					
						
							| 
									
										
										
										
											2020-06-16 11:26:54 +02:00
										 |  |  | from pony.orm import Database, db_session | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 11:26:54 +02:00
										 |  |  | from flask import Flask, flash, request, redirect, url_for, render_template, Response | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | from werkzeug.utils import secure_filename | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 11:26:54 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 09:45:23 +02:00
										 |  |  | UPLOAD_FOLDER = os.path.relpath('uploads') | 
					
						
							|  |  |  | LOGS_FOLDER = os.path.relpath('logs') | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | multidata_folder = os.path.join(UPLOAD_FOLDER, "multidata") | 
					
						
							|  |  |  | os.makedirs(multidata_folder, exist_ok=True) | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | os.makedirs(LOGS_FOLDER, exist_ok=True) | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def allowed_file(filename): | 
					
						
							|  |  |  |     return filename.endswith('multidata') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | app = Flask(__name__) | 
					
						
							|  |  |  | app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER | 
					
						
							|  |  |  | app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024  # 1 megabyte limit | 
					
						
							|  |  |  | app.config["SECRET_KEY"] = os.urandom(32) | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | app.config["PONY"] = { | 
					
						
							|  |  |  |     'provider': 'sqlite', | 
					
						
							|  |  |  |     'filename': 'db.db3', | 
					
						
							|  |  |  |     'create_db': True | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | db = Database() | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | name = "localhost" | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | multiworlds = {} | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | class Multiworld(): | 
					
						
							|  |  |  |     def __init__(self, multidata: str): | 
					
						
							|  |  |  |         self.multidata = multidata | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  |         self.process: typing.Optional[multiprocessing.Process] = None | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  |         multiworlds[multidata] = self | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def start(self): | 
					
						
							|  |  |  |         if self.process and self.process.is_alive(): | 
					
						
							| 
									
										
										
										
											2020-06-13 22:49:57 +02:00
										 |  |  |             return False | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  |         logging.info(f"Spinning up {self.multidata}") | 
					
						
							|  |  |  |         self.process = multiprocessing.Process(group=None, target=run_server_process, | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  |                                                args=(self.multidata,), | 
					
						
							|  |  |  |                                                name="MultiHost") | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  |         self.process.start() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def stop(self): | 
					
						
							|  |  |  |         if self.process: | 
					
						
							|  |  |  |             self.process.terminate() | 
					
						
							|  |  |  |             self.process = None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | @app.route('/', methods=['GET', 'POST']) | 
					
						
							|  |  |  | def upload_multidata(): | 
					
						
							|  |  |  |     if request.method == 'POST': | 
					
						
							|  |  |  |         # check if the post request has the file part | 
					
						
							|  |  |  |         if 'file' not in request.files: | 
					
						
							|  |  |  |             flash('No file part') | 
					
						
							|  |  |  |             return redirect(request.url) | 
					
						
							|  |  |  |         file = request.files['file'] | 
					
						
							|  |  |  |         # if user does not select file, browser also | 
					
						
							|  |  |  |         # submit an empty part without filename | 
					
						
							|  |  |  |         if file.filename == '': | 
					
						
							|  |  |  |             flash('No selected file') | 
					
						
							|  |  |  |             return redirect(request.url) | 
					
						
							|  |  |  |         if file and allowed_file(file.filename): | 
					
						
							|  |  |  |             filename = secure_filename(file.filename) | 
					
						
							|  |  |  |             file.save(os.path.join(multidata_folder, filename)) | 
					
						
							|  |  |  |             return redirect(url_for('host_multidata', | 
					
						
							|  |  |  |                                     filename=filename)) | 
					
						
							| 
									
										
										
										
											2020-06-13 22:49:57 +02:00
										 |  |  |     return render_template("upload_multidata.html") | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | def _read_log(path: str): | 
					
						
							| 
									
										
										
										
											2020-06-14 08:11:56 +02:00
										 |  |  |     if os.path.exists(path): | 
					
						
							|  |  |  |         with open(path) as log: | 
					
						
							|  |  |  |             yield from log | 
					
						
							|  |  |  |     else: | 
					
						
							| 
									
										
										
										
											2020-06-14 09:45:23 +02:00
										 |  |  |         yield f"Logfile {path} does not exist. " \ | 
					
						
							|  |  |  |               f"Likely a crash during spinup of multiworld instance or it is still spinning up." | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | @app.route('/log/<filename>') | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | def display_log(filename: str): | 
					
						
							| 
									
										
										
										
											2020-06-14 09:45:23 +02:00
										 |  |  |     filename = secure_filename(filename) | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  |     # noinspection PyTypeChecker | 
					
						
							|  |  |  |     return Response(_read_log(os.path.join("logs", filename + ".txt")), mimetype="text/plain;charset=UTF-8") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | processstartlock = threading.Lock() | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @app.route('/hosted/<filename>') | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | def host_multidata(filename: str): | 
					
						
							|  |  |  |     with db_session: | 
					
						
							| 
									
										
										
										
											2020-06-14 08:18:31 +02:00
										 |  |  |         multiworld = multiworlds.get(filename, None) | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  |         if not multiworld: | 
					
						
							| 
									
										
										
										
											2020-06-14 08:18:31 +02:00
										 |  |  |             multiworld = Multiworld(filename) | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         with processstartlock: | 
					
						
							|  |  |  |             multiworld.start() | 
					
						
							| 
									
										
										
										
											2020-06-13 10:16:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  |     return render_template("host_multidata.html", filename=filename) | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-16 11:26:54 +02:00
										 |  |  | from WebHost.customserver import run_server_process | 
					
						
							| 
									
										
										
										
											2020-06-13 08:37:05 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     multiprocessing.freeze_support() | 
					
						
							| 
									
										
										
										
											2020-06-14 09:45:23 +02:00
										 |  |  |     multiprocessing.set_start_method('spawn') | 
					
						
							| 
									
										
										
										
											2020-06-14 07:44:59 +02:00
										 |  |  |     db.bind(**app.config["PONY"]) | 
					
						
							|  |  |  |     db.generate_mapping(create_tables=True) | 
					
						
							|  |  |  |     app.run(debug=True) |