Skip to content

Instantly share code, notes, and snippets.

@jessehub
Created March 9, 2017 19:36
Show Gist options
  • Save jessehub/e3241950067daa0f21c3509e995deb22 to your computer and use it in GitHub Desktop.
Save jessehub/e3241950067daa0f21c3509e995deb22 to your computer and use it in GitHub Desktop.
snapshot lambda
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