From 238cc67ebb80122286bbe609c80af9297892884e Mon Sep 17 00:00:00 2001 From: WasinUddy Date: Wed, 20 Nov 2024 15:23:10 +0700 Subject: [PATCH] fix(s3): unable to backup --- CHANGELOG.md | 4 ++ backend/minecraft_server.py | 80 +++++++++++++++++++++++++------------ 2 files changed, 59 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index afca2dd..a040e1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [2.0.6] - 2024-11-20 +### Fixed +- Fixed unable to backup to AWS S3 + ## [2.0.5] - 2024-11-20 ### Fixed - boto3 module not found fix by using requirments.txt within Dockerfile diff --git a/backend/minecraft_server.py b/backend/minecraft_server.py index 31d2223..ec79394 100644 --- a/backend/minecraft_server.py +++ b/backend/minecraft_server.py @@ -107,30 +107,60 @@ def send_command(self, command_string: str): def save_data(self): """ Save the server persistent data to AWS S3 bucket. + Handles cleanup of temporary files and directories in case of failures. + + Raises: + Exception: If there are errors during the backup process """ - self.stop() - - os.mkdir('./tmp') - - # Copy the world data to a temporary directory - shutil.copytree('./instance/worlds', './tmp/worlds') - - # Copy the config files to a temporary directory - for config_file in self.config_files: - shutil.copy(f'./configs/{config_file}', f'./tmp/{config_file}') - - # Zip the temporary directory - shutil.make_archive('./tmp', 'zip', './tmp') - - # Upload the zip file to AWS S3 - self.s3.upload_file( - './tmp.zip', - settings.AWS_S3_BUCKET_NAME, - f'{settings.INSTANCE_NAME}_{int(time.time())}_backup.zip' - ) - - # Cleanup - shutil.rmtree('./tmp') - os.remove('./tmp.zip') + tmp_dir = './tmp' + zip_file = './tmp.zip' + + try: + # Stop the server first + self.stop() + + # Clean up any existing temporary files from failed previous attempts + if os.path.exists(tmp_dir): + shutil.rmtree(tmp_dir) + if os.path.exists(zip_file): + os.remove(zip_file) + + # Create fresh temporary directory + os.makedirs(tmp_dir) + + # Copy the world data to temporary directory + shutil.copytree('./instance/worlds', os.path.join(tmp_dir, 'worlds')) + + # Copy the config files to temporary directory + for config_file in self.config_files: + shutil.copy(f'./configs/{config_file}', os.path.join(tmp_dir, config_file)) + + # Create zip archive + shutil.make_archive('./tmp', 'zip', tmp_dir) + + # Verify S3 bucket exists before attempting upload + try: + self.s3.head_bucket(Bucket=settings.AWS_S3_BUCKET_NAME) + except Exception as e: + raise Exception(f"S3 bucket '{settings.AWS_S3_BUCKET_NAME}' is not accessible: {str(e)}") + + # Upload to S3 + backup_key = f'{settings.INSTANCE_NAME}_{int(time.time())}_backup.zip' + self.s3.upload_file( + zip_file, + settings.AWS_S3_BUCKET_NAME, + backup_key + ) - self.start() + except Exception as e: + raise Exception(f"Failed to create backup: {str(e)}") + + finally: + # Cleanup temporary files + if os.path.exists(tmp_dir): + shutil.rmtree(tmp_dir) + if os.path.exists(zip_file): + os.remove(zip_file) + + # Restart the server + self.start()