-
Notifications
You must be signed in to change notification settings - Fork 3
/
backup_data.py
107 lines (92 loc) · 3.07 KB
/
backup_data.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import time
import datetime
import logging
import boto.ec2
import boto.exception
from .config import (
AWS_REGION, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,
)
logger = logging.getLogger('maas')
def delete_old_snapshots(conn, vol_id, exclude_snap):
"""
We get only one volume by vol_id and delete all snapshots of it
excluding exclude_snap and 3 last snapshots
"""
try:
# get volume by volume id
volume = conn.get_all_volumes([vol_id])[0]
snapshots = volume.snapshots()
snapshots_sorted = sorted([(s, s.start_time) for s in snapshots],
key=lambda k: k[1])[4:]
for snapshot, start_time in snapshots_sorted:
if snapshot.id == exclude_snap:
continue
info = "deleting snap {id}: {desc}".format(
id=snapshot.id, desc=snapshot.description)
logger.info(info)
snapshot.delete()
except (boto.exception.EC2ResponseError) as e:
logger.error(e)
def manage_snapshots(conn, vol_id):
"""
Create a snapshot, delete old ones
"""
retry = 0
snapshot = None
while (retry < 3):
try:
# create a snapshot
at_time = datetime.datetime.today().strftime("%d-%m-%Y %H:%M:%S")
desc = "Vol:{vol};Date:{date}".format(vol=vol_id, date=at_time)
snapshot = conn.create_snapshot(vol_id, desc)
info = "snapshot created has id: {}".format(snapshot.id)
logger.info(info)
break
except (boto.exception.EC2ResponseError, AssertionError) as e:
retry += 1
logger.error(e)
if not snapshot:
return
while snapshot.status != 'completed':
time.sleep(2)
snapshot.update()
if snapshot.status == 'error':
return
delete_old_snapshots(conn, vol_id, snapshot.id)
def extract_non_root_id(bdm):
"""
Get id of non root volume (data volume in our case)
"""
try:
bd = bdm['blockDeviceMapping']['/dev/xvdf']
return bd.volume_id
# case when we don't have data volume is also possible
except KeyError:
return None
def manage_instances_snapshots():
"""
Connect to aws, create snapshots for all instances that have data volume,
delete old data volumes snapshots
"""
retry = 0
instances = []
while (retry < 3):
try:
conn = boto.ec2.connect_to_region(
AWS_REGION,
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY
)
instances = conn.get_only_instances()
break
except (boto.exception.EC2ResponseError, AssertionError) as e:
retry += 1
logger.error(e)
if not instances:
logger.error('Max retries exceeded for instance receiving')
return
for instance in instances:
data_vol_id = extract_non_root_id(
instance.get_attribute("blockDeviceMapping"))
if data_vol_id:
manage_snapshots(conn, data_vol_id)