11import boto3
2- import collections
3- import datetime
4- import os
5-
6- ec = boto3 .client ('ec2' )
7-
8- def lambda_handler (event , context ):
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 (
25- Filters = [
26- { 'Name' : 'tag:Backup' , 'Values' : ['Yes' ] },
27- ]
28- ).get (
29- 'Reservations' , []
30- )
31-
32- print "Found %d instances that need backing up" % len (instances [0 ]['Instances' ])
33-
34- # Initialise Dictionary Objects To Store Tags In
35- to_tag = collections .defaultdict (list )
36-
37- # Iterate Over Each Instance & SnapShot Volumes Not Explicitly Excluded From Backups
38- for instance in instances [0 ]['Instances' ]:
39-
40- # List All Volumes Attached To The Instance
41- for dev in instance ['BlockDeviceMappings' ]:
42-
43- # Set Variable Defaults
44- snapshot_required = True
45- volume_name = None
46-
47- if dev .get ('Ebs' , None ) is None :
48- continue
49- vol_id = dev ['Ebs' ]['VolumeId' ]
50- dev_name = dev ['DeviceName' ]
51-
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 "\t Ignoring EBS volume %s (%s) on instance %s - 'Backup' Tag set to 'No'" % (
72- vol_id ,
73- dev_name ,
74- instance ['InstanceId' ]
75- )
76-
77- else :
78- print "\t Found 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)
2+ import collections
3+ import datetime
4+ import os
5+
6+ ec = boto3 .client ('ec2' )
7+
8+ def lambda_handler (event , context ):
9+
10+ # Get Current Region
11+ aws_region = os .getenv ('AWS_REGION' )
12+
13+ # Determine Which Instances To SnapShot
14+ instances = ec .describe_instances (
15+ Filters = [
16+ { 'Name' : 'tag:Backup' , 'Values' : ['Yes' ] },
17+ ]
18+ ).get (
19+ 'Reservations' , []
20+ )[0 ]['Instances' ]
21+
22+ print "Found %d instances that need backing up" % len (instances )
23+
24+ # Iterate Over Each Instance & SnapShot Volumes Not Explicitly Excluded From Backups
25+ for instance in instances :
26+
27+ # Determine Retention Period Based Upon Tags
28+ retention_days = 7
29+ destination_region = None
8530 instance_name = ""
8631 for tag in instance ['Tags' ]:
87- if tag ['Key' ] != 'Name' :
88- continue
89- else :
90- instance_name = tag ['Value' ]
32+ if tag ['Key' ] == 'RetentionDays' and tag ['Value' ] > 0 :
33+ retention_days = int (tag ['Value' ])
34+
35+ if tag ['Key' ] == 'DestinationRegion' and len (tag ['Value' ]) > 0 :
36+ destination_region = tag ['Value' ]
37+
38+ if tag ['Key' ] == 'Name' and len (tag ['Value' ]) > 0 :
39+ instance_name = tag ['Value' ]
40+
41+ print "Setting SnapShot retention period To %s days" % (retention_days )
42+
43+ # Determine When We're Going To Delete This SnapShot
44+ delete_date = datetime .date .today () + datetime .timedelta (days = retention_days )
45+ delete_fmt = delete_date .strftime ('%Y-%m-%d' )
46+
47+ # Set Default SnapShot Tags
48+ snapshot_tags = [
49+ { 'Key' : 'DeleteOn' , 'Value' : delete_fmt },
50+ { 'Key' : 'Type' , 'Value' : 'Automated' },
51+ ]
52+
53+ # If We Want To Offsite This SnapShot, Set The Appropriate Tag
54+ if destination_region != None :
55+ snapshot_tags = snapshot_tags + [{ 'Key' : 'DestinationRegion' , 'Value' : destination_region }]
56+
57+ # List All Volumes Attached To The Instance
58+ for dev in instance ['BlockDeviceMappings' ]:
59+
60+ # Set Variable Defaults
61+ snapshot_required = True
62+ volume_name = None
63+
64+ if dev .get ('Ebs' , None ) is None :
65+ continue
66+ vol_id = dev ['Ebs' ]['VolumeId' ]
67+ dev_name = dev ['DeviceName' ]
68+
69+ # Get a Volume Object Based Upon Volume ID
70+ volume = ec .describe_volumes (
71+ VolumeIds = [vol_id ,]
72+ )['Volumes' ][0 ]
73+
74+ # Set Default SnapShot Description
75+ description = '%s - %s (%s)' % (
76+ instance_name ,
77+ vol_id ,
78+ dev_name
79+ )
80+
81+ if 'Tags' in volume :
82+ for tag in volume ['Tags' ]:
83+
84+ # Determine If Volume Has 'Backup' Flag Set To 'No' & Exclude From SnapShot If It Does
85+ if tag ['Key' ] == 'Backup' and tag ['Value' ] == 'No' :
86+ snapshot_required = False
87+
88+ # Override Default Description With Volume Name If One Specified
89+ if tag ['Key' ] == 'Name' :
90+ description = tag ['Value' ]
91+
9192
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
93+ # We Don't Want To SnapShot Any Volume Explictly Excluded
94+ if snapshot_required == False :
95+ print " \t Ignoring EBS volume %s (%s) on instance %s - 'Backup' Tag set to 'No'" % (
96+ vol_id ,
97+ dev_name ,
98+ instance [ 'InstanceId' ]
9899 )
99- else :
100- description = volume_name
100+
101+ continue
102+
103+
104+ print "\t Found EBS volume %s (%s) on instance %s - Proceeding with SnapShot" % (
105+ vol_id ,
106+ dev_name ,
107+ instance ['InstanceId' ]
108+ )
101109
102- # Trigger SnapShot
103- snap = ec .create_snapshot (
110+ # Take SnapShot Of Volume
111+ snap = ec .create_snapshot (
104112 VolumeId = vol_id ,
105113 Description = description
106- )
107-
108- if (snap ):
109- print "\t \t Snapshot %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 \t Retaining snapshot %s of volume %s from instance %s (%s) for %d days" % (
114+ )
115+
116+ if not (snap ):
117+ print "\t \t SnapShot operation failed!"
118+ continue
119+
120+ print " \t \t Snapshot %s created in %s of [%s]" % (
121+ snap [ 'SnapshotId' ],
122+ aws_region ,
123+ description
124+ )
125+
126+ print "\t \t Retaining snapshot %s of volume %s from instance %s (%s) for %d days" % (
119127 snap ['SnapshotId' ],
120128 vol_id ,
121129 instance ['InstanceId' ],
122130 instance_name ,
123131 retention_days ,
124- )
125-
126- for retention_days in to_tag .keys ():
127- delete_date = datetime .date .today () + datetime .timedelta (days = retention_days )
128- delete_fmt = delete_date .strftime ('%Y-%m-%d' )
129- print "Will delete %d snapshots from %s on %s" % (
130- len (to_tag [retention_days ]),
131- aws_region ,
132- delete_fmt
133- )
134-
135- ec .create_tags (
136- Resources = to_tag [retention_days ],
137- Tags = [
138- { 'Key' : 'DeleteOn' , 'Value' : delete_fmt },
139- { 'Key' : 'Type' , 'Value' : 'Automated' },
140- ]
141- )
132+ )
133+
134+ # Tag The SnapShot To Facilitate Later Automated Deletion & Offsiting
135+ ec .create_tags (
136+ Resources = [snap ['SnapshotId' ]],
137+ Tags = snapshot_tags
138+ )
0 commit comments