diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..ed5eacb1 Binary files /dev/null and b/.DS_Store differ diff --git a/app/classes/shared/helpers.py b/app/classes/shared/helpers.py index 1610869f..96f645a0 100644 --- a/app/classes/shared/helpers.py +++ b/app/classes/shared/helpers.py @@ -12,6 +12,7 @@ import logging import html import zipfile import pathlib +import shutil from datetime import datetime from socket import gethostname @@ -561,5 +562,31 @@ class Helpers: zf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.join(path, '..'))) + @staticmethod + def copy_files(source, dest): + if os.path.isfile(source): + shutil.copyfile(source, dest) + logger.info("Copying jar %s to %s", source, dest) + else: + logger.info("Source jar does not exist.") + + @staticmethod + def download_file(executable_url, jar_path): + try: + r = requests.get(executable_url, timeout=5) + except Exception as ex: + logger.error("Could not download executable: %s", ex) + return False + if r.status_code != 200: + logger.error("Unable to download file from %s", executable_url) + return False + + try: + open(jar_path, "wb").write(r.content) + except Exception as e: + logger.error("Unable to finish executable download. Error: %s", e) + return False + return True + helper = Helpers() diff --git a/app/classes/shared/models.py b/app/classes/shared/models.py index 4b470eb8..99ac6454 100644 --- a/app/classes/shared/models.py +++ b/app/classes/shared/models.py @@ -122,6 +122,7 @@ class Servers(BaseModel): auto_start_delay = IntegerField(default=10) crash_detection = BooleanField(default=0) stop_command = CharField(default="stop") + executable_update_url = CharField(default="") server_ip = CharField(default="127.0.0.1") server_port = IntegerField(default=25565) logs_delete_after = IntegerField(default=0) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index c770bf5d..6d03c7fe 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -42,6 +42,7 @@ class Server: self.settings = None self.updating = False self.server_id = None + self.jar_update_url = None self.name = None self.is_crashed = False self.restart_count = 0 @@ -341,3 +342,39 @@ class Server: return [{"path": os.path.relpath(f['path'], start=conf['backup_path']), "size": f["size"]} for f in files] else: return [] + + def jar_update(self): + #checks if server is running. Calls shutdown if it is running. + if self.check_running(): + logger.info("Server with PID %s is running. Sending shutdown command", self.PID) + self.stop_threaded_server() + else: + backup_dir = os.path.join(self.settings['path'], 'crafty_executable_backups') + #checks if backup directory already exists + if os.path.isdir(backup_dir): + backup_executable = os.path.join(backup_dir, 'old_server.jar') + else: + logger.info("Executable backup directory not found for Server: {}}. Creating one.", self.name) + os.mkdir(backup_dir) + backup_executable = os.path.join(backup_dir, 'old_server.jar') + + if os.path.isfile(backup_executable): + #removes old backup + logger.info("Old backup found for server: {}. Removing...", self.name) + os.remove(backup_executable) + logger.info("Old backup removed for server: {}.", self.name) + else: + logger.info("No old backups found for server: {}", self.name) + + current_executable = os.path.join(self.settings['path'], self.settings['executable']) + + #copies to backup dir + helper.copy_files(current_executable, backup_executable) + + #boolean returns true for false for success + downloaded = helper.download_file(self.settings['executable_update_url'], current_executable) + + if downloaded: + logger.info("Executable updated successfully.") + else: + logger.error("Executable download failed.") diff --git a/app/classes/shared/tasks.py b/app/classes/shared/tasks.py index bc572379..d50123e3 100644 --- a/app/classes/shared/tasks.py +++ b/app/classes/shared/tasks.py @@ -110,6 +110,9 @@ class TasksManager: elif command == "backup_server": svr.backup_server() + elif command == "update_executable": + svr.jar_update() + db_helper.mark_command_complete(c.get('command_id', None)) time.sleep(1) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 65347e33..dd3dbcc2 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -426,6 +426,7 @@ class PanelHandler(BaseHandler): auto_start_delay = self.get_argument('auto_start_delay', '10') server_ip = self.get_argument('server_ip', None) server_port = self.get_argument('server_port', None) + executable_update_url = self.get_argument('executable_update_url', None) auto_start = int(float(self.get_argument('auto_start', '0'))) crash_detection = int(float(self.get_argument('crash_detection', '0'))) logs_delete_after = int(float(self.get_argument('logs_delete_after', '0'))) @@ -454,6 +455,7 @@ class PanelHandler(BaseHandler): Servers.server_ip: server_ip, Servers.server_port: server_port, Servers.auto_start: auto_start, + Servers.executable_update_url: executable_update_url, Servers.crash_detection: crash_detection, Servers.logs_delete_after: logs_delete_after, }).where(Servers.server_id == server_id).execute() diff --git a/app/frontend/templates/panel/server_config.html b/app/frontend/templates/panel/server_config.html index c08639c9..156b3154 100644 --- a/app/frontend/templates/panel/server_config.html +++ b/app/frontend/templates/panel/server_config.html @@ -106,6 +106,11 @@ +