Skip to content

Commit ad78253

Browse files
author
Dave Osment
committed
Updated creator to get all variables from Tags. Added functionality to exclude individual Volumes attached to an Instance from SnapShots and added support for off-site tag. Configured description to use Volume Name where specified.
1 parent 8f38cda commit ad78253

File tree

1 file changed

+106
-46
lines changed

1 file changed

+106
-46
lines changed

ebs-snapshot-creator.py

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,141 @@
11
import boto3
22
import collections
33
import datetime
4-
5-
region = 'us-west-2' # region we're running in (should be changed to be auto-determined
4+
import os
65

76
ec = boto3.client('ec2')
87

98
def lambda_handler(event, context):
10-
reservations = ec.describe_instances(
9+
10+
# Get Current Region
11+
aws_region = os.getenv('AWS_REGION')
12+
13+
# Get Retention Period From Environment Variable Or Assume Default If Not Specified
14+
retention_days = int(
15+
os.getenv(
16+
'RETENTION_DAYS',
17+
7
18+
)
19+
)
20+
21+
print "Setting SnapShot retention period To %s days" % (retention_days)
22+
23+
# Determine Which Instances To SnapShot
24+
instances = ec.describe_instances(
1125
Filters=[
1226
{ 'Name': 'tag:Backup', 'Values': ['Yes'] },
1327
]
1428
).get(
1529
'Reservations', []
1630
)
31+
32+
print "Found %d instances that need backing up" % len(instances[0]['Instances'])
1733

18-
instances = sum(
19-
[
20-
[i for i in r['Instances']]
21-
for r in reservations
22-
], [])
23-
24-
print "Found %d instances that need backing up" % len(instances)
25-
34+
# Initialise Dictionary Objects To Store Tags In
2635
to_tag = collections.defaultdict(list)
2736

28-
for instance in instances:
29-
try:
30-
retention_days = [
31-
int(t.get('Value')) for t in instance['Tags']
32-
if t['Key'] == 'Retention'][0]
33-
except IndexError:
34-
retention_days = 7
37+
# Iterate Over Each Instance & SnapShot Volumes Not Explicitly Excluded From Backups
38+
for instance in instances[0]['Instances']:
3539

40+
# List All Volumes Attached To The Instance
3641
for dev in instance['BlockDeviceMappings']:
42+
43+
# Set Variable Defaults
44+
snapshot_required = True
45+
volume_name = None
46+
3747
if dev.get('Ebs', None) is None:
3848
continue
3949
vol_id = dev['Ebs']['VolumeId']
4050
dev_name = dev['DeviceName']
41-
print "\tFound EBS volume %s (%s) on instance %s" % (
42-
vol_id, dev_name, instance['InstanceId'])
43-
44-
# figure out instance name if there is one
45-
instance_name = ""
46-
for tag in instance['Tags']:
47-
if tag['Key'] != 'Name':
48-
continue
49-
else:
50-
instance_name = tag['Value']
5151

52-
description = '%s - %s (%s)' % ( instance_name, vol_id, dev_name )
53-
54-
# trigger snapshot
55-
snap = ec.create_snapshot(
56-
VolumeId=vol_id,
57-
Description=description
52+
# Get a Volume Object Based Upon Volume ID
53+
volume = ec.describe_volumes(
54+
VolumeIds=[vol_id,]
55+
)
56+
57+
vol = volume['Volumes'][0]
58+
if 'Tags' in vol:
59+
for tag in vol['Tags']:
60+
61+
# Determine If Volume Has 'Backup' Flag Set To 'No' & Exclude From SnapShot If It Does
62+
if tag['Key'] == 'Backup' and tag['Value'] == 'No':
63+
snapshot_required = False
64+
65+
# Determine If Volume Has a Name Specified
66+
if tag['Key'] == 'Name':
67+
volume_name = tag['Value']
68+
69+
# Exit This Loop If SnapShot Not Required
70+
if snapshot_required == False:
71+
print "\tIgnoring EBS volume %s (%s) on instance %s - 'Backup' Tag set to 'No'" % (
72+
vol_id,
73+
dev_name,
74+
instance['InstanceId']
5875
)
5976

60-
if (snap):
61-
print "\t\tSnapshot %s created in %s of [%s]" % ( snap['SnapshotId'], region, description )
62-
to_tag[retention_days].append(snap['SnapshotId'])
63-
print "\t\tRetaining snapshot %s of volume %s from instance %s (%s) for %d days" % (
64-
snap['SnapshotId'],
65-
vol_id,
66-
instance['InstanceId'],
67-
instance_name,
68-
retention_days,
69-
)
77+
else:
78+
print "\tFound EBS volume %s (%s) on instance %s - Proceeding with SnapShot" % (
79+
vol_id,
80+
dev_name,
81+
instance['InstanceId']
82+
)
83+
84+
# Determine EC2 Instance Name (If Present)
85+
instance_name = ""
86+
for tag in instance['Tags']:
87+
if tag['Key'] != 'Name':
88+
continue
89+
else:
90+
instance_name = tag['Value']
91+
92+
# Determine SnapShot Description (Use Volume Name If Specified)
93+
if volume_name == None:
94+
description = '%s - %s (%s)' % (
95+
instance_name,
96+
vol_id,
97+
dev_name
98+
)
99+
else:
100+
description = volume_name
101+
102+
# Trigger SnapShot
103+
snap = ec.create_snapshot(
104+
VolumeId=vol_id,
105+
Description=description
106+
)
107+
108+
if (snap):
109+
print "\t\tSnapshot %s created in %s of [%s]" % (
110+
snap['SnapshotId'],
111+
aws_region,
112+
description
113+
)
114+
115+
# Tag The SnapShot To Facilitate Later Automated Deletion
116+
to_tag[retention_days].append(snap['SnapshotId'])
117+
118+
print "\t\tRetaining snapshot %s of volume %s from instance %s (%s) for %d days" % (
119+
snap['SnapshotId'],
120+
vol_id,
121+
instance['InstanceId'],
122+
instance_name,
123+
retention_days,
124+
)
70125

71126
for retention_days in to_tag.keys():
72127
delete_date = datetime.date.today() + datetime.timedelta(days=retention_days)
73128
delete_fmt = delete_date.strftime('%Y-%m-%d')
74-
print "Will delete %d snapshots on %s" % (len(to_tag[retention_days]), delete_fmt)
129+
print "Will delete %d snapshots from %s on %s" % (
130+
len(to_tag[retention_days]),
131+
aws_region,
132+
delete_fmt
133+
)
134+
75135
ec.create_tags(
76136
Resources=to_tag[retention_days],
77137
Tags=[
78138
{ 'Key': 'DeleteOn', 'Value': delete_fmt },
79139
{ 'Key': 'Type', 'Value': 'Automated' },
80140
]
81-
)
141+
)

0 commit comments

Comments
 (0)