7.16.2013

AWS: EC2 Restore Script

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

 

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

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

コード

#!/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 件のコメント:

コメントを投稿