Created
March 9, 2017 19:36
-
-
Save jessehub/e3241950067daa0f21c3509e995deb22 to your computer and use it in GitHub Desktop.
snapshot lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import boto3 | |
import json | |
import datetime | |
def respond(err, res=None): | |
return { | |
'statusCode': '400' if err else '200', | |
'body': err.message if err else json.dumps(res, default=str), | |
'headers': { | |
'Content-Type': 'application/json', | |
}, | |
} | |
# these should be separate AWS Lambdas | |
def create(ebsid, hostname, device, tags): | |
ec2 = boto3.client('ec2') | |
snapshot = ec2.create_snapshot( | |
VolumeId=ebsid, | |
Description="%s:%s" % (hostname, device) | |
) | |
ec2.create_tags(Resources=[snapshot.get('SnapshotId')], Tags=tagfilter(tags)) | |
return snapshot | |
def delete(snapshotids): | |
ec2 = boto3.client('ec2') | |
for i in snapshotids: | |
ec2.delete_snapshot(SnapshotId = i) | |
return snapshotids | |
def search(hostname, device): | |
ec2 = boto3.client('ec2') | |
snapshots = [] | |
pages = ec2.get_paginator('describe_snapshots').paginate( | |
Filters=[{'Name': 'description', 'Values': ["%s:%s" % (hostname, device)]}] | |
) | |
for page in pages: | |
for snap in page['Snapshots']: | |
snapshots.append(snap) | |
return snapshots | |
def tagfilter(dirtytags = []): | |
cleantags = [] | |
for t in dirtytags: | |
if t['Key'][:4] != 'aws:': | |
cleantags.append(t) | |
return cleantags | |
# event requires hostname, device(default 0), period(no), oldest(no) | |
def lambda_handler(event, context): | |
ec2 = boto3.client('ec2') | |
if event.get('hostname') is None: | |
return respond(ValueError('hostname is required')) | |
result = ec2.describe_instances( | |
Filters=[ | |
{ | |
'Name': 'tag:Name', | |
'Values': [ | |
event['hostname'], | |
] | |
} | |
]) | |
if len(result['Reservations']) != 1: | |
return respond (RuntimeError("no matching hostname")) | |
instance = result['Reservations'][0]['Instances'][0] | |
tags = instance['Tags'] | |
devices = sorted(instance['BlockDeviceMappings'], key=lambda d: d['DeviceName']) | |
offset = event.get('device', 0) | |
ebsid = devices[offset]['Ebs']['VolumeId'] | |
snapshots = search(event['hostname'], event['device']) | |
nowish = datetime.datetime.utcnow() | |
oldsnaps = [] | |
result = {} | |
for snap in snapshots: | |
if (snap['StartTime'].replace(tzinfo=None) > nowish - datetime.timedelta(hours=event['period'])): | |
result['SnapshotId'] = snap['SnapshotId'] | |
if ('oldest' in event) and (snap['StartTime'].replace(tzinfo=None) < nowish - datetime.timedelta(hours=event['oldest'])): | |
oldsnaps.append(snap['SnapshotId']) | |
if 'SnapshotId' not in result: | |
result['SnapshotId'] = create(ebsid, event['hostname'], event['device'], tags).get('SnapshotId') | |
result['Deleted'] = delete(oldsnaps) | |
# result would be nice to have status of retained snapshots (Completed, In Progress, Failed) | |
return respond(None, result) | |
if __name__ == "__main__": | |
import sys | |
print lambda_handler(event={ | |
'hostname': sys.argv[1], | |
'device': int(sys.argv[2]), | |
'period': int(sys.argv[3]), | |
'oldest': int(sys.argv[4])},context=None) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment