Skip to content

Instantly share code, notes, and snippets.

@uurtech
Created December 29, 2025 18:44
Show Gist options
  • Select an option

  • Save uurtech/2eb0af5390e84e0a1e2fd18373baad2c to your computer and use it in GitHub Desktop.

Select an option

Save uurtech/2eb0af5390e84e0a1e2fd18373baad2c to your computer and use it in GitHub Desktop.
glacier to standart
#!/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()
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