Created
December 29, 2025 18:44
-
-
Save uurtech/2eb0af5390e84e0a1e2fd18373baad2c to your computer and use it in GitHub Desktop.
glacier to standart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Simple Glacier to Standard S3 Migration Script | |
| Usage: python glacier_to_s3.py | |
| """ | |
| import boto3 | |
| import time | |
| # ============ CONFIGURATION ============ | |
| BUCKET = "your-bucket-name" | |
| FOLDER = "your/folder/prefix/" | |
| REGION = "us-east-1" | |
| RESTORE_DAYS = 7 | |
| TIER = "Standard" # Expedited (1-5min), Standard (3-5hrs), Bulk (5-12hrs) | |
| # ======================================= | |
| s3 = boto3.client('s3', region_name=REGION) | |
| GLACIER_CLASSES = ['GLACIER'] | |
| def list_glacier_objects(): | |
| """List all Glacier objects in the folder.""" | |
| objects = [] | |
| paginator = s3.get_paginator('list_objects_v2') | |
| for page in paginator.paginate(Bucket=BUCKET, Prefix=FOLDER): | |
| for obj in page.get('Contents', []): | |
| if obj.get('StorageClass', 'STANDARD') in GLACIER_CLASSES: | |
| objects.append(obj['Key']) | |
| return objects | |
| def get_restore_status(key): | |
| """Check if object is restored.""" | |
| resp = s3.head_object(Bucket=BUCKET, Key=key) | |
| restore = resp.get('Restore', '') | |
| if 'ongoing-request="false"' in restore: | |
| return 'ready' | |
| elif 'ongoing-request="true"' in restore: | |
| return 'in_progress' | |
| return 'not_started' | |
| def restore_object(key): | |
| """Initiate restore for a Glacier object.""" | |
| try: | |
| s3.restore_object( | |
| Bucket=BUCKET, | |
| Key=key, | |
| RestoreRequest={'Days': RESTORE_DAYS, 'GlacierJobParameters': {'Tier': TIER}} | |
| ) | |
| print(f"✓ Restore initiated: {key}") | |
| except s3.exceptions.ClientError as e: | |
| if 'RestoreAlreadyInProgress' in str(e): | |
| print(f"⏳ Already restoring: {key}") | |
| else: | |
| print(f"✗ Error: {key} - {e}") | |
| def copy_to_standard(key): | |
| """Copy restored object to Standard storage.""" | |
| try: | |
| s3.copy_object( | |
| CopySource={'Bucket': BUCKET, 'Key': key}, | |
| Bucket=BUCKET, | |
| Key=key, | |
| StorageClass='STANDARD', | |
| MetadataDirective='COPY' | |
| ) | |
| print(f"✓ Copied to Standard: {key}") | |
| except Exception as e: | |
| print(f"✗ Copy failed: {key} - {e}") | |
| def main(): | |
| print(f"Bucket: {BUCKET}") | |
| print(f"Folder: {FOLDER}") | |
| print("-" * 50) | |
| # Step 1: Find Glacier objects | |
| print("\n[1/3] Finding Glacier objects...") | |
| objects = list_glacier_objects() | |
| print(f"Found {len(objects)} Glacier objects") | |
| if not objects: | |
| print("Nothing to migrate!") | |
| return | |
| # Step 2: Initiate restore | |
| print("\n[2/3] Initiating restore...") | |
| for key in objects: | |
| status = get_restore_status(key) | |
| if status == 'ready': | |
| print(f"⏩ Already restored: {key}") | |
| elif status == 'in_progress': | |
| print(f"⏳ Restore in progress: {key}") | |
| else: | |
| restore_object(key) | |
| # Step 3: Wait and copy | |
| print("\n[3/3] Waiting for restore & copying...") | |
| pending = objects.copy() | |
| while pending: | |
| still_pending = [] | |
| for key in pending: | |
| status = get_restore_status(key) | |
| if status == 'ready': | |
| copy_to_standard(key) | |
| else: | |
| still_pending.append(key) | |
| pending = still_pending | |
| if pending: | |
| print(f"\n⏳ {len(pending)} objects still restoring... waiting 5 min") | |
| time.sleep(300) | |
| print("\n" + "=" * 50) | |
| print("✅ Migration complete!") | |
| if __name__ == '__main__': | |
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| boto3>=1.26.0 | |
| botocore>=1.29.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment