7.16.2013

AWS: EC2 Restore Script

AWS: EC2インスタンスをスナップショットから復元するスクリプト

 

スナップショットのリストアに伴う一連の操作をスクリプト化。

デバイスが EBS 1個だけの場合にのみ対応。

コード

aws_restore.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys
import subprocess
import time
try:
    import json
except ImportError:
    print('You need python 2.6 or later to run this script.')
    sys.exit(1)
 
 
def usage():
    print('Usage: %s <instance-id> <snapshot-id>' % sys.argv[0])
    sys.exit(2)
 
 
def run_command(*args):
    output = subprocess.check_output(['aws', 'ec2'] + list(args))
    return json.loads(output)
 
 
def get_volume_id(instance):
    assert(len(instance['BlockDeviceMappings']) == 1)
    return instance['BlockDeviceMappings'][0]['Ebs']['VolumeId']
 
 
def get_zone(instance):
    return instance['Placement']['AvailabilityZone']
 
 
def get_device(instance):
    assert(len(instance['BlockDeviceMappings']) == 1)
    return instance['BlockDeviceMappings'][0]['DeviceName']
 
 
def is_running(instance):
    return instance['State']['Code'] == 16
 
 
def is_stopped(instance):
    return instance['State']['Code'] == 80
 
 
def get_instance(instance_id):
    j = run_command('describe-instances', '--instance-ids', instance_id)
    return j['Reservations'][0]['Instances'][0]
 
 
def start_instance(instance_id):
    sys.stdout.write('Starting instance: %s ...' % instance_id)
    run_command('start-instances', '--instance-ids', instance_id)
 
    for i in range(20):
        sys.stdout.write('.')
        time.sleep(10)
        if is_running(get_instance(instance_id)):
            break
    else:
        raise(RunTimeError('Timed out for waiting.'))
    print('OK')
 
 
def stop_instance(instance_id):
    sys.stdout.write('Stopping instance: %s ...' % instance_id)
    run_command('stop-instances', '--instance-ids', instance_id)
 
    for i in range(20):
        sys.stdout.write('.')
        time.sleep(10)
        if is_stopped(get_instance(instance_id)):
            break
    else:
        raise(RunTimeError('Timed out for waiting.'))
    print('OK')
 
 
def detach_volume(volume_id):
    sys.stdout.write('Detaching volume: %s ...' % volume_id)
    run_command('detach-volume', '--volume-id', volume_id)
    print('OK')
 
 
def create_volume(zone, snapshot):
    sys.stdout.write('Creating volume from snapshot: %s ...' % snapshot)
    j = run_command(
        'create-volume', '--availability-zone', zone,
        '--snapshot-id', snapshot)
    print('OK')
    return j['VolumeId']
 
 
def attach_volume(volume_id, instance_id, device):
    sys.stdout.write('Attaching volume: %s ...' % volume_id)
    run_command(
        'attach-volume', '--volume-id', volume_id,
        '--instance-id', instance_id, '--device', device)
    print('OK')
 
 
def delete_volume(volume_id):
    sys.stdout.write('Deleting volume: %s ...' % volume_id)
    run_command('delete-volume', '--volume-id', volume_id)
    print('OK')
 
 
if __name__ == '__main__':
    if len(sys.argv) != 3:
        usage()
 
    instance_id = sys.argv[1]
    snapshot = sys.argv[2]
 
    sys.stdout.write('Checking instance: %s ...' % instance_id)
    ins = get_instance(instance_id)
 
    old_vol = get_volume_id(ins)
    print('OK')
 
    stop_instance(instance_id)
    detach_volume(old_vol)
    new_vol = create_volume(get_zone(ins), snapshot)
    attach_volume(new_vol, instance_id, get_device(ins))
    start_instance(instance_id)
    delete_volume(old_vol)

実行例

$ ./aws_restore.py i-xxxxxxxx snap-XXXXXXXX
Checking instance: i-xxxxxxxx ...OK
Stopping instance: i-xxxxxxxx .......OK
Detaching volume: vol-yyyyyyyy ...OK
Creating volume from snapshot: snap-XXXXXXXX ...OK
Attaching volume: vol-zzzzzzzz ...OK
Starting instance: i-xxxxxxxx .....OK
Deleting volume: vol-yyyyyyyy ...OK

0 件のコメント:

コメントを投稿