Here is the script to auto delete those snapshot that is older than n days
Requirements
- Python
- Boto >=2.4.0
option list
-k = access key ID
-s = secret access key
-a = how many days
-d = description contain
-r = region
example
ec2-rotate-snapshot.py -k AKIAert5EYQKJBN6TASQ -s 8ka5hp9lDOPjDNOJsdfnmaHcMWAsdamoWbH4HhBj -a 5 -d "backup" -r eu-west-1
this will check snapshot that is more than 5 day and contain word "backup" in region eu-west-1 and proceed to delete
reference/source
I get this from https://bitbucket.org/romabysen/ec2-rotate-snapshots/overview
owner is Lars Hansson
so please feel free to thanks him for this wonderful script
Script start here
--------------------------------------------------------------------------------
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# :copyright: (c) 2013 by Lars Hansson.
# :license: ISC, see LICENSE for more details.
#
"""Utility for rotating EC2 snaphots"""
import os
import sys
import time
import logging
from optparse import OptionParser
import datetime
import re
import boto.ec2
DEFAULT_REGION = boto.ec2.EC2Connection.DefaultRegionName
def setup_logging(level):
logger = logging.getLogger('ec2-rotate-snapshot')
ch = logging.StreamHandler()
logger.setLevel(level)
logger.addHandler(ch)
def log_err(msg):
logger = logging.getLogger('ec2-rotate-snapshot')
logger.error(msg)
def log_info(msg):
logger = logging.getLogger('ec2-rotate-snapshot')
logger.info(msg)
def match_tags(tags, m_tags):
if not m_tags:
return True
for item in m_tags:
if item.find('=') != -1:
(tag, value) = item.split('=')
for k, v in tags.items():
if k == tag and v == value:
return True
else:
if item in tags.keys():
return True
return False
def match_timeframe(start_time, timeframe):
if not timeframe:
return True
dt_start_time = datetime.datetime.strptime(start_time, '%Y-%m-%dT%H:%M:%S.%fZ')
(start, end) = timeframe.split('-')
frame_start = dt_start_time.replace(hour=int(start.split(':')[0]),
minute=int(start.split(':')[1]),
second=0)
frame_end = dt_start_time.replace(hour=int(end.split(':')[0]),
minute=int(end.split(':')[1]),
second=0)
if frame_end < frame_start:
frame_end = frame_end + datetime.timedelta(days=+1)
return frame_start <= dt_start_time <= frame_end
def match_age(start_time, age):
if not age:
return True
st = time.strptime(start_time, '%Y-%m-%dT%H:%M:%S.%fZ')
at = time.gmtime(time.time() - (86400 * age))
return st < at
def match_string(mstring, pattern):
if not pattern:
return True
if not mstring:
return False
if re.search(pattern, mstring) is not None:
return True
return False
def cleanup_snapshots(pattern, opts):
conn = boto.ec2.connect_to_region(opts.region)
for snap in conn.get_all_snapshots(owner='self'):
if (match_string(snap.description, pattern) and match_tags(snap.tags, opts.tag) and
match_timeframe(snap.start_time, opts.timeframe) and
match_age(snap.start_time, opts.age)):
if opts.delete:
try:
conn.delete_snapshot(snap.id)
except boto.exception.EC2ResponseError:
# Retry deleting since sometimes random errors happen
try:
time.sleep(2)
conn.delete_snapshot(snap.id)
except boto.exception.EC2ResponseError:
log_err('Error! Snapshot %s not deleted' % (snap.id))
continue
log_info('Snapshot deleted: %s' % (snap.id))
time.sleep(0.5)
else:
log_info('Snapshot: %s, start time: %s, description: %s, tags: %s' %
(snap.id, snap.start_time, snap.description, snap.tags.keys()))
def handle_options():
"""Parse commandline options"""
usage = 'Usage: %prog [options] <regular expression>'
version = '%prog 0.1.0'
parser = OptionParser(usage=usage, version=version)
parser.add_option('-k', dest='key', help='AWS access key id')
parser.add_option('-s', dest='secret', help='AWS secret access key')
parser.add_option('-r', dest='region', help='Region. Default: %s' % (DEFAULT_REGION))
parser.add_option('-a', dest='age', type='int', default=None,
help='Older than these many days')
parser.add_option('-t', action='append', dest='tag', default=None,
help='Match this tag and, optionally, content')
parser.add_option('-T', dest='timeframe', default=None,
help='Timeframe selector. Example: 15:30-15:45')
parser.add_option('-d', dest='delete', action='store_true', default=False,
help='Actually delete instead of printing the matches')
parser.add_option('-q', action='store_true', default=False, dest='quiet', help='Only print errors')
(opts, args) = parser.parse_args()
if opts.quiet:
setup_logging(logging.ERROR)
else:
setup_logging(logging.INFO)
if opts.key is not None:
os.environ["AWS_ACCESS_KEY_ID"] = opts.key
if opts.secret is not None:
os.environ["AWS_SECRET_ACCESS_KEY"] = opts.secret
if len(args) == 0:
log_err('A regular expression is required.')
parser.print_usage()
sys.exit(1)
if len(args) > 1:
log_err('Too many regular expressions.')
parser.print_usage()
sys.exit(1)
return (opts, args)
def main():
"""The main loop"""
(opts, args) = handle_options()
pattern = args[0]
cleanup_snapshots(pattern, opts)
if __name__ == '__main__':
main()
No comments:
Post a Comment