<s> """<STR_LIT>""" <EOL> import logging <EOL> from time import sleep <EOL> from boto . ec2 import connect_to_region , EC2Connection <EOL> from boto . ec2 . blockdevicemapping import BlockDeviceMapping , BlockDeviceType <EOL> from boto . ec2 . image import Image <EOL> from boto . ec2 . instance import Instance <EOL> from boto . ec2 . volume import Volume <EOL> from boto . exception import EC2ResponseError <EOL> from boto . utils import get_instance_metadata <EOL> from decorator import decorator <EOL> from os import environ <EOL> from aminator . config import conf_action <EOL> from aminator . exceptions import FinalizerException , VolumeException <EOL> from aminator . plugins . cloud . base import BaseCloudPlugin <EOL> from aminator . util import retry <EOL> from aminator . util . linux import device_prefix , native_block_device , os_node_exists <EOL> from aminator . util . metrics import timer , raises , succeeds , lapse <EOL> __all__ = ( '<STR_LIT>' , ) <EOL> log = logging . getLogger ( __name__ ) <EOL> def registration_retry ( ExceptionToCheck = ( EC2ResponseError , ) , tries = <NUM_LIT:3> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:1> , logger = None ) : <EOL> """<STR_LIT>""" <EOL> if logger is None : <EOL> logger = log <EOL> @ decorator <EOL> def _retry ( f , * args , ** kwargs ) : <EOL> _tries , _delay = tries , delay <EOL> total_tries = _tries <EOL> args , kwargs = args , kwargs <EOL> while _tries > <NUM_LIT:0> : <EOL> try : <EOL> return f ( * args , ** kwargs ) <EOL> except ExceptionToCheck , e : <EOL> if e . error_code == '<STR_LIT>' : <EOL> log . debug ( '<STR_LIT>' . format ( kwargs [ '<STR_LIT:name>' ] ) ) <EOL> attempt = abs ( _tries - ( total_tries + <NUM_LIT:1> ) ) <EOL> kwargs [ '<STR_LIT:name>' ] = kwargs . pop ( '<STR_LIT:name>' ) + str ( attempt ) <EOL> log . debug ( '<STR_LIT>' . format ( kwargs [ '<STR_LIT:name>' ] ) ) <EOL> sleep ( _delay ) <EOL> _tries -= <NUM_LIT:1> <EOL> _delay *= backoff <EOL> else : <EOL> for ( code , msg ) in e . errors : <EOL> log . critical ( '<STR_LIT>' . format ( code , msg ) ) <EOL> return False <EOL> log . critical ( '<STR_LIT>' ) <EOL> return False <EOL> return _retry <EOL> class EC2CloudPlugin ( BaseCloudPlugin ) : <EOL> _name = '<STR_LIT>' <EOL> def add_metrics ( self , metric_base_name , cls , func_name ) : <EOL> newfunc = succeeds ( "<STR_LIT>" . format ( metric_base_name ) , self ) ( raises ( "<STR_LIT>" . format ( metric_base_name ) , self ) ( timer ( "<STR_LIT>" . format ( metric_base_name ) , self ) ( getattr ( cls , func_name ) ) ) ) <EOL> setattr ( cls , func_name , newfunc ) <EOL> def __init__ ( self ) : <EOL> super ( EC2CloudPlugin , self ) . __init__ ( ) <EOL> for ec2func in [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] : <EOL> self . add_metrics ( "<STR_LIT>" . format ( ec2func ) , EC2Connection , ec2func ) <EOL> for volfunc in [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] : <EOL> self . add_metrics ( "<STR_LIT>" . format ( volfunc ) , Volume , volfunc ) <EOL> for imgfunc in [ "<STR_LIT>" ] : <EOL> self . add_metrics ( "<STR_LIT>" . format ( imgfunc ) , Image , imgfunc ) <EOL> for insfunc in [ "<STR_LIT>" ] : <EOL> self . add_metrics ( "<STR_LIT>" . format ( insfunc ) , Instance , insfunc ) <EOL> def add_plugin_args ( self , * args , ** kwargs ) : <EOL> context = self . _config . context <EOL> base_ami = self . _parser . add_argument_group ( title = '<STR_LIT>' , description = '<STR_LIT>' ) <EOL> base_ami_mutex = base_ami . add_mutually_exclusive_group ( required = True ) <EOL> base_ami_mutex . add_argument ( '<STR_LIT>' , '<STR_LIT>' , dest = '<STR_LIT>' , action = conf_action ( config = context . ami ) , help = '<STR_LIT>' ) <EOL> base_ami_mutex . add_argument ( '<STR_LIT>' , '<STR_LIT>' , dest = '<STR_LIT>' , action = conf_action ( config = context . ami ) , help = '<STR_LIT>' ) <EOL> cloud = self . _parser . add_argument_group ( title = '<STR_LIT>' , description = '<STR_LIT>' ) <EOL> cloud . add_argument ( '<STR_LIT>' , '<STR_LIT>' , dest = '<STR_LIT>' , help = '<STR_LIT>' , action = conf_action ( config = context . cloud ) ) <EOL> cloud . add_argument ( '<STR_LIT>' , dest = '<STR_LIT>' , help = '<STR_LIT>' , action = conf_action ( config = context . cloud , action = '<STR_LIT:store_true>' ) ) <EOL> cloud . add_argument ( '<STR_LIT>' , dest = '<STR_LIT>' , help = '<STR_LIT>' , action = conf_action ( config = context . cloud , action = '<STR_LIT:store_true>' ) ) <EOL> cloud . add_argument ( '<STR_LIT>' , '<STR_LIT>' , dest = '<STR_LIT>' , action = conf_action ( config = context . ami ) , help = '<STR_LIT>' ) <EOL> def configure ( self , config , parser ) : <EOL> super ( EC2CloudPlugin , self ) . configure ( config , parser ) <EOL> host = config . context . web_log . get ( '<STR_LIT:host>' , False ) <EOL> if not host : <EOL> md = get_instance_metadata ( ) <EOL> pub , ipv4 = '<STR_LIT>' , '<STR_LIT>' <EOL> config . context . web_log [ '<STR_LIT:host>' ] = md [ pub ] if pub in md else md [ ipv4 ] <EOL> def connect ( self , ** kwargs ) : <EOL> if self . _connection : <EOL> log . warn ( '<STR_LIT>' ) <EOL> else : <EOL> log . info ( '<STR_LIT>' ) <EOL> self . _connect ( ** kwargs ) <EOL> def _connect ( self , ** kwargs ) : <EOL> cloud_config = self . _config . plugins [ self . full_name ] <EOL> context = self . _config . context <EOL> self . _instance_metadata = get_instance_metadata ( ) <EOL> instance_region = self . _instance_metadata [ '<STR_LIT>' ] [ '<STR_LIT>' ] [ : - <NUM_LIT:1> ] <EOL> region = kwargs . pop ( '<STR_LIT>' , context . get ( '<STR_LIT>' , cloud_config . get ( '<STR_LIT>' , instance_region ) ) ) <EOL> log . debug ( '<STR_LIT>' . format ( region ) ) <EOL> context . cloud . setdefault ( '<STR_LIT>' , False ) <EOL> if context . cloud . boto_debug : <EOL> from aminator . config import configure_datetime_logfile <EOL> configure_datetime_logfile ( self . _config , '<STR_LIT>' ) <EOL> kwargs [ '<STR_LIT>' ] = <NUM_LIT:1> <EOL> log . debug ( '<STR_LIT>' ) <EOL> else : <EOL> logging . getLogger ( '<STR_LIT>' ) . setLevel ( logging . INFO ) <EOL> if '<STR_LIT>' not in kwargs : <EOL> kwargs [ '<STR_LIT>' ] = context . get ( '<STR_LIT>' , cloud_config . get ( '<STR_LIT>' , True ) ) <EOL> self . _connection = connect_to_region ( region , ** kwargs ) <EOL> log . info ( '<STR_LIT>' . format ( region ) ) <EOL> def allocate_base_volume ( self , tag = True ) : <EOL> cloud_config = self . _config . plugins [ self . full_name ] <EOL> context = self . _config . context <EOL> self . _volume = Volume ( connection = self . _connection ) <EOL> rootdev = context . base_ami . block_device_mapping [ context . base_ami . root_device_name ] <EOL> self . _volume . id = self . _connection . create_volume ( size = rootdev . size , zone = self . _instance . placement , snapshot = rootdev . snapshot_id ) . id <EOL> if not self . _volume_available ( ) : <EOL> log . critical ( '<STR_LIT>' ) <EOL> return False <EOL> if tag : <EOL> tags = { <EOL> '<STR_LIT>' : cloud_config . get ( '<STR_LIT>' , '<STR_LIT>' ) , <EOL> '<STR_LIT:status>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : context . base_ami . id , <EOL> '<STR_LIT>' : context . base_ami . name , <EOL> '<STR_LIT>' : context . base_ami . architecture , <EOL> } <EOL> self . _connection . create_tags ( [ self . _volume . id ] , tags ) <EOL> self . _volume . update ( ) <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id ) ) <EOL> @ retry ( VolumeException , tries = <NUM_LIT:2> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:2> , logger = log ) <EOL> def attach_volume ( self , blockdevice , tag = True ) : <EOL> context = self . _config . context <EOL> if "<STR_LIT>" in context . ami : <EOL> volumes = self . _connection . get_all_volumes ( volume_ids = [ context . ami . volume_id ] ) <EOL> if not volumes : <EOL> raise VolumeException ( '<STR_LIT>' . format ( context . ami . volume_id ) ) <EOL> self . _volume = volumes [ <NUM_LIT:0> ] <EOL> return <EOL> self . allocate_base_volume ( tag = tag ) <EOL> ec2_device_name = blockdevice . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , ec2_device_name , blockdevice ) ) <EOL> self . _volume . attach ( self . _instance . id , ec2_device_name ) <EOL> if not self . is_volume_attached ( blockdevice ) : <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , ec2_device_name , blockdevice ) ) <EOL> self . _volume . add_tag ( '<STR_LIT:status>' , '<STR_LIT>' ) <EOL> raise VolumeException ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , blockdevice ) ) <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , blockdevice ) ) <EOL> def is_volume_attached ( self , blockdevice ) : <EOL> context = self . _config . context <EOL> if "<STR_LIT>" in context . ami : <EOL> return True <EOL> try : <EOL> self . _volume_attached ( blockdevice ) <EOL> except VolumeException : <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , blockdevice ) ) <EOL> return False <EOL> return True <EOL> @ retry ( VolumeException , tries = <NUM_LIT:10> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:2> , logger = log ) <EOL> def _volume_attached ( self , blockdevice ) : <EOL> status = self . _volume . update ( ) <EOL> if status != '<STR_LIT>' : <EOL> raise VolumeException ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id , blockdevice ) ) <EOL> elif not os_node_exists ( blockdevice ) : <EOL> raise VolumeException ( '<STR_LIT>' . format ( blockdevice ) ) <EOL> else : <EOL> return True <EOL> def snapshot_volume ( self , description = None ) : <EOL> context = self . _config . context <EOL> if not description : <EOL> description = context . snapshot . get ( '<STR_LIT:description>' , '<STR_LIT>' ) <EOL> log . debug ( '<STR_LIT>' . format ( description ) ) <EOL> self . _snapshot = self . _volume . create_snapshot ( description ) <EOL> if not self . _snapshot_complete ( ) : <EOL> log . critical ( '<STR_LIT>' ) <EOL> return False <EOL> else : <EOL> log . debug ( '<STR_LIT>' . format ( self . _snapshot . id ) ) <EOL> return True <EOL> def _state_check ( self , obj , state ) : <EOL> obj . update ( ) <EOL> classname = obj . __class__ . __name__ <EOL> if classname in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> if classname == '<STR_LIT>' : <EOL> log . debug ( "<STR_LIT>" . format ( obj . id , obj . status , obj . progress ) ) <EOL> return obj . status == state <EOL> else : <EOL> return obj . state == state <EOL> @ retry ( VolumeException , tries = <NUM_LIT> , delay = <NUM_LIT:0.5> , backoff = <NUM_LIT> , logger = log , maxdelay = <NUM_LIT:10> ) <EOL> def _wait_for_state ( self , resource , state ) : <EOL> if self . _state_check ( resource , state ) : <EOL> log . debug ( '<STR_LIT>' . format ( resource . __class__ . __name__ , state ) ) <EOL> return True <EOL> else : <EOL> raise VolumeException ( '<STR_LIT>' . format ( resource . id , state , resource . status ) ) <EOL> @ lapse ( "<STR_LIT>" ) <EOL> def _ami_available ( self ) : <EOL> return self . _wait_for_state ( self . _ami , '<STR_LIT>' ) <EOL> @ lapse ( "<STR_LIT>" ) <EOL> def _snapshot_complete ( self ) : <EOL> return self . _wait_for_state ( self . _snapshot , '<STR_LIT>' ) <EOL> @ lapse ( "<STR_LIT>" ) <EOL> def _volume_available ( self ) : <EOL> return self . _wait_for_state ( self . _volume , '<STR_LIT>' ) <EOL> def detach_volume ( self , blockdevice ) : <EOL> context = self . _config . context <EOL> if "<STR_LIT>" in context . ami : <EOL> return <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id ) ) <EOL> self . _volume . detach ( ) <EOL> if not self . _volume_detached ( blockdevice ) : <EOL> raise VolumeException ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id ) ) <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id ) ) <EOL> @ retry ( VolumeException , tries = <NUM_LIT:7> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:2> , logger = log ) <EOL> def _volume_detached ( self , blockdevice ) : <EOL> status = self . _volume . update ( ) <EOL> if status != '<STR_LIT>' : <EOL> raise VolumeException ( '<STR_LIT>' . format ( self . _volume . id , self . _instance . id ) ) <EOL> elif os_node_exists ( blockdevice ) : <EOL> raise VolumeException ( '<STR_LIT>' . format ( blockdevice ) ) <EOL> else : <EOL> return True <EOL> def delete_volume ( self ) : <EOL> context = self . _config . context <EOL> if "<STR_LIT>" in context . ami : <EOL> return True <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id ) ) <EOL> self . _volume . delete ( ) <EOL> return self . _volume_deleted ( ) <EOL> def _volume_deleted ( self ) : <EOL> try : <EOL> self . _volume . update ( ) <EOL> except EC2ResponseError , e : <EOL> if e . code == '<STR_LIT>' : <EOL> log . debug ( '<STR_LIT>' . format ( self . _volume . id ) ) <EOL> return True <EOL> return False <EOL> def is_stale_attachment ( self , dev , prefix ) : <EOL> log . debug ( '<STR_LIT>' . format ( dev , prefix ) ) <EOL> if dev in self . attached_block_devices ( prefix ) and not os_node_exists ( dev ) : <EOL> log . debug ( '<STR_LIT>' . format ( dev ) ) <EOL> return True <EOL> log . debug ( '<STR_LIT>' . format ( dev ) ) <EOL> return False <EOL> @ registration_retry ( tries = <NUM_LIT:3> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:1> ) <EOL> def _register_image ( self , ** ami_metadata ) : <EOL> context = self . _config . context <EOL> ami = Image ( connection = self . _connection ) <EOL> ami . id = self . _connection . register_image ( ** ami_metadata ) <EOL> if ami . id is None : <EOL> return False <EOL> else : <EOL> while True : <EOL> try : <EOL> sleep ( <NUM_LIT:2> ) <EOL> ami . update ( ) <EOL> break <EOL> except EC2ResponseError , e : <EOL> if e . error_code == '<STR_LIT>' : <EOL> log . debug ( '<STR_LIT>' . format ( ami . id ) ) <EOL> else : <EOL> raise e <EOL> log . info ( '<STR_LIT>' . format ( ami . id , ami . name ) ) <EOL> context . ami . image = self . _ami = ami <EOL> return True <EOL> def register_image ( self , * args , ** kwargs ) : <EOL> context = self . _config . context <EOL> vm_type = context . ami . get ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> if '<STR_LIT>' in kwargs : <EOL> ami_metadata = { <EOL> '<STR_LIT:name>' : context . ami . name , <EOL> '<STR_LIT:description>' : context . ami . description , <EOL> '<STR_LIT>' : kwargs [ '<STR_LIT>' ] , <EOL> '<STR_LIT>' : vm_type <EOL> } <EOL> else : <EOL> block_device_map , root_block_device = args [ : <NUM_LIT:2> ] <EOL> bdm = self . _make_block_device_map ( block_device_map , root_block_device ) <EOL> ami_metadata = { <EOL> '<STR_LIT:name>' : context . ami . name , <EOL> '<STR_LIT:description>' : context . ami . description , <EOL> '<STR_LIT>' : bdm , <EOL> '<STR_LIT>' : root_block_device , <EOL> '<STR_LIT>' : context . base_ami . kernel_id , <EOL> '<STR_LIT>' : context . base_ami . ramdisk_id , <EOL> '<STR_LIT>' : context . base_ami . architecture , <EOL> '<STR_LIT>' : vm_type <EOL> } <EOL> if vm_type == "<STR_LIT>" : <EOL> del ami_metadata [ '<STR_LIT>' ] <EOL> del ami_metadata [ '<STR_LIT>' ] <EOL> if vm_type == '<STR_LIT>' : <EOL> if context . ami . get ( "<STR_LIT>" , False ) : <EOL> ami_metadata [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> if not self . _register_image ( ** ami_metadata ) : <EOL> return False <EOL> return True <EOL> def _make_block_device_map ( self , block_device_map , root_block_device ) : <EOL> bdm = BlockDeviceMapping ( connection = self . _connection ) <EOL> bdm [ root_block_device ] = BlockDeviceType ( snapshot_id = self . _snapshot . id , delete_on_termination = True ) <EOL> for ( os_dev , ec2_dev ) in block_device_map : <EOL> bdm [ os_dev ] = BlockDeviceType ( ephemeral_name = ec2_dev ) <EOL> return bdm <EOL> @ retry ( FinalizerException , tries = <NUM_LIT:3> , delay = <NUM_LIT:1> , backoff = <NUM_LIT:2> , logger = log ) <EOL> def add_tags ( self , resource_type ) : <EOL> context = self . _config . context <EOL> log . debug ( '<STR_LIT>' . format ( resource_type ) ) <EOL> tags = context [ resource_type ] . get ( '<STR_LIT>' , None ) <EOL> if not tags : <EOL> log . critical ( '<STR_LIT>' . format ( resource_type ) ) <EOL> return False <EOL> instance_var = '<STR_LIT:_>' + resource_type <EOL> try : <EOL> instance = getattr ( self , instance_var ) <EOL> except Exception : <EOL> errstr = '<STR_LIT>' . format ( instance_var ) <EOL> log . debug ( errstr , exc_info = True ) <EOL> log . critical ( errstr ) <EOL> return False <EOL> else : <EOL> try : <EOL> self . _connection . create_tags ( [ instance . id ] , tags ) <EOL> except EC2ResponseError : <EOL> errstr = '<STR_LIT>' <EOL> errstr = errstr . format ( resource_type , instance . id ) <EOL> log . critical ( errstr ) <EOL> raise FinalizerException ( errstr ) <EOL> else : <EOL> log . debug ( '<STR_LIT>' . format ( resource_type , instance . id ) ) <EOL> instance . update ( ) <EOL> tagstring = '<STR_LIT:\n>' . join ( '<STR_LIT:=>' . join ( ( key , val ) ) for ( key , val ) in tags . iteritems ( ) ) <EOL> log . debug ( '<STR_LIT>' . format ( tagstring ) ) <EOL> return True <EOL> def attached_block_devices ( self , prefix ) : <EOL> log . debug ( '<STR_LIT>' . format ( prefix ) ) <EOL> self . _instance . update ( ) <EOL> if device_prefix ( self . _instance . block_device_mapping . keys ( ) [ <NUM_LIT:0> ] ) != prefix : <EOL> return dict ( ( native_block_device ( dev , prefix ) , mapping ) for ( dev , mapping ) in self . _instance . block_device_mapping . iteritems ( ) ) <EOL> return self . _instance . block_device_mapping <EOL> def _resolve_baseami ( self ) : <EOL> log . info ( '<STR_LIT>' ) <EOL> context = self . _config . context <EOL> cloud_config = self . _config . plugins [ self . full_name ] <EOL> try : <EOL> ami_id = context . ami . get ( '<STR_LIT>' , cloud_config . get ( '<STR_LIT>' , None ) ) <EOL> if ami_id is None : <EOL> ami_id = context . ami . get ( '<STR_LIT>' , cloud_config . get ( '<STR_LIT>' , None ) ) <EOL> if ami_id is None : <EOL> raise RuntimeError ( '<STR_LIT>' ) <EOL> else : <EOL> context . ami [ '<STR_LIT>' ] = ami_id <EOL> log . info ( '<STR_LIT>' . format ( ami_id ) ) <EOL> baseami = self . _connection . get_all_images ( image_ids = [ ami_id ] ) [ <NUM_LIT:0> ] <EOL> else : <EOL> log . info ( '<STR_LIT>' . format ( ami_id ) ) <EOL> baseami = self . _connection . get_all_images ( filters = { '<STR_LIT:name>' : ami_id } ) [ <NUM_LIT:0> ] <EOL> except IndexError : <EOL> raise RuntimeError ( '<STR_LIT>' . format ( ami_id ) ) <EOL> log . info ( '<STR_LIT>' . format ( baseami ) ) <EOL> context [ '<STR_LIT>' ] = baseami <EOL> def __enter__ ( self ) : <EOL> self . connect ( ) <EOL> self . _resolve_baseami ( ) <EOL> self . _instance = Instance ( connection = self . _connection ) <EOL> self . _instance . id = get_instance_metadata ( ) [ '<STR_LIT>' ] <EOL> self . _instance . update ( ) <EOL> context = self . _config . context <EOL> if context . ami . get ( "<STR_LIT>" , None ) : <EOL> environ [ "<STR_LIT>" ] = context . ami . base_ami_name <EOL> if context . ami . get ( "<STR_LIT>" , None ) : <EOL> environ [ "<STR_LIT>" ] = context . ami . base_ami_id <EOL> if context . cloud . get ( "<STR_LIT>" , None ) : <EOL> environ [ "<STR_LIT>" ] = context . cloud . region <EOL> return self </s>
