Skip to content

Commit 7b0ad57

Browse files
author
Sanjay Prabhakar
committed
[patch] downloadFromS3
1 parent 86d7ebd commit 7b0ad57

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

src/mas/devops/backup.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,98 @@ def uploadToS3(
316316
except Exception as e:
317317
logger.error(f"Unexpected error uploading to S3: {e}")
318318
return False
319+
320+
321+
def downloadFromS3(
322+
bucket_name: str,
323+
object_name: str,
324+
local_dir: str,
325+
endpoint_url=None,
326+
aws_access_key_id=None,
327+
aws_secret_access_key=None,
328+
region_name=None
329+
) -> bool:
330+
"""
331+
Download a tar.gz file from S3-compatible storage to a backup directory.
332+
333+
Args:
334+
bucket_name: Name of the S3 bucket
335+
object_name: S3 object name to download
336+
local_dir: Directory path where the file will be downloaded
337+
endpoint_url: S3-compatible endpoint URL (e.g., for MinIO, Ceph)
338+
aws_access_key_id: AWS access key ID (if not using environment variables)
339+
aws_secret_access_key: AWS secret access key (if not using environment variables)
340+
region_name: AWS region name (default: us-east-1)
341+
342+
Returns:
343+
bool: True if file was downloaded successfully, False otherwise
344+
"""
345+
# Validate backup directory
346+
if not os.path.exists(local_dir):
347+
logger.info(f"Backup directory does not exist, creating: {local_dir}")
348+
try:
349+
os.makedirs(local_dir, exist_ok=True)
350+
except Exception as e:
351+
logger.error(f"Failed to create backup directory {local_dir}: {e}")
352+
return False
353+
354+
# Construct the full file path
355+
file_path = os.path.join(local_dir, object_name)
356+
357+
# Warn if file doesn't have .tar.gz extension
358+
if not object_name.endswith('.tar.gz'):
359+
logger.warning(f"Object does not have .tar.gz extension: {object_name}")
360+
361+
# Configure S3 client
362+
try:
363+
s3_config = {}
364+
365+
if endpoint_url:
366+
s3_config['endpoint_url'] = endpoint_url
367+
if aws_access_key_id and aws_secret_access_key:
368+
s3_config['aws_access_key_id'] = aws_access_key_id
369+
s3_config['aws_secret_access_key'] = aws_secret_access_key
370+
if region_name:
371+
s3_config['region_name'] = region_name
372+
else:
373+
s3_config['region_name'] = 'us-east-1'
374+
375+
s3_client = boto3.client('s3', **s3_config)
376+
377+
# Check if object exists and get its size
378+
logger.info(f"Downloading s3://{bucket_name}/{object_name} to {file_path}")
379+
380+
try:
381+
response = s3_client.head_object(Bucket=bucket_name, Key=object_name)
382+
file_size = response.get('ContentLength', 0)
383+
logger.info(f"Object size: {file_size / (1024 * 1024):.2f} MB")
384+
except ClientError as e:
385+
if e.response.get('Error', {}).get('Code') == '404':
386+
logger.error(f"Object not found in S3: s3://{bucket_name}/{object_name}")
387+
return False
388+
raise
389+
390+
# Download the file
391+
s3_client.download_file(bucket_name, object_name, file_path)
392+
393+
# Verify the downloaded file exists
394+
if os.path.exists(file_path):
395+
downloaded_size = os.path.getsize(file_path)
396+
logger.info(f"Successfully downloaded {object_name} to {file_path}")
397+
logger.info(f"Downloaded file size: {downloaded_size / (1024 * 1024):.2f} MB")
398+
return True
399+
else:
400+
logger.error(f"Download completed but file not found at {file_path}")
401+
return False
402+
403+
except NoCredentialsError:
404+
logger.error("AWS credentials not found. Please provide credentials or configure environment variables.")
405+
return False
406+
except ClientError as e:
407+
error_code = e.response.get('Error', {}).get('Code', 'Unknown')
408+
error_message = e.response.get('Error', {}).get('Message', str(e))
409+
logger.error(f"S3 client error ({error_code}): {error_message}")
410+
return False
411+
except Exception as e:
412+
logger.error(f"Unexpected error downloading from S3: {e}")
413+
return False

0 commit comments

Comments
 (0)