11import boto3
22import collections
33import datetime
4-
5- region = 'us-west-2' # region we're running in (should be changed to be auto-determined
4+ import os
65
76ec = boto3 .client ('ec2' )
87
98def 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 "\t Found 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 "\t Ignoring 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 \t Snapshot %s created in %s of [%s]" % ( snap ['SnapshotId' ], region , description )
62- to_tag [retention_days ].append (snap ['SnapshotId' ])
63- print "\t \t Retaining 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 "\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)
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 \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" % (
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