<s> import itertools <EOL> import os <EOL> import time <EOL> from kokki import Provider , Fail <EOL> class EBSVolumeProvider ( Provider ) : <EOL> def action_create ( self ) : <EOL> if self . resource . volume_id : <EOL> raise Fail ( "<STR_LIT>" ) <EOL> vol = self . _find_volume ( self . resource . volume_id , self . resource . name , self . resource . device ) <EOL> if vol : <EOL> self . log . debug ( "<STR_LIT>" , self . resource ) <EOL> else : <EOL> vol = self . _create_volume ( self . resource . snapshot_id , self . resource . size , self . resource . availability_zone , self . resource . name , self . resource . timeout ) <EOL> self . resource . updated ( ) <EOL> def action_attach ( self ) : <EOL> vol = self . _determine_volume ( ) <EOL> if vol . status == "<STR_LIT>" : <EOL> if vol . attach_data . instance_id != self . resource . env . config . aws . instance_id : <EOL> raise Fail ( "<STR_LIT>" % ( vol . id , vol . attach_data . instance_id ) ) <EOL> else : <EOL> self . log . debug ( "<STR_LIT>" ) <EOL> else : <EOL> self . _attach_volume ( vol , self . resource . env . config . aws . instance_id , self . resource . device , self . resource . timeout ) <EOL> self . resource . updated ( ) <EOL> def action_detach ( self ) : <EOL> vol = self . _determine_volume ( ) <EOL> if not vol . attach_data or vol . attach_data . instance_id != self . resource . env . config . aws . instance_id : <EOL> return <EOL> self . _detach_volume ( vol , self . resource . timeout ) <EOL> self . resource . updated ( ) <EOL> def action_snapshot ( self ) : <EOL> vol = self . _determine_volume ( ) <EOL> snapshot = self . ec2 . create_snapshot ( vol . id ) <EOL> self . resource . updated ( ) <EOL> self . log . info ( "<STR_LIT>" % ( vol . id , snapshot . id ) ) <EOL> def _find_volume ( self , volume_id = None , name = None , device = None ) : <EOL> vol = None <EOL> if volume_id : <EOL> vol = self . _volume_by_id ( volume_id ) <EOL> else : <EOL> all_volumes = [ v for v in self . ec2 . get_all_volumes ( ) if v . status in ( '<STR_LIT>' , '<STR_LIT>' ) ] <EOL> if device : <EOL> for v in all_volumes : <EOL> if v . attach_data and v . attach_data . device == device and v . attach_data . instance_id == self . resource . env . config . aws . instance_id : <EOL> vol = v <EOL> break <EOL> if not vol and name : <EOL> if '<STR_LIT>' in name : <EOL> allnames = dict ( ( v . tags . get ( '<STR_LIT:Name>' ) , v ) for v in all_volumes ) <EOL> for i in itertools . count ( <NUM_LIT:1> ) : <EOL> vname = name . format ( index = i ) <EOL> try : <EOL> v = allnames [ vname ] <EOL> if v . status == "<STR_LIT>" : <EOL> vol = v <EOL> break <EOL> except KeyError : <EOL> self . resource . name = vname <EOL> break <EOL> else : <EOL> for v in all_volumes : <EOL> if v . tags . get ( '<STR_LIT:Name>' ) == name : <EOL> vol = v <EOL> break <EOL> if vol and '<STR_LIT>' in name : <EOL> self . resource . name = vol . tags . get ( '<STR_LIT:Name>' ) <EOL> return vol <EOL> def _determine_volume ( self ) : <EOL> """<STR_LIT>""" <EOL> vol = self . _find_volume ( self . resource . volume_id , self . resource . name , self . resource . device ) <EOL> if not vol : <EOL> raise Fail ( "<STR_LIT>" ) <EOL> return vol <EOL> def _volume_by_id ( self , volume_id ) : <EOL> """<STR_LIT>""" <EOL> volumes = self . ec2 . get_all_volumes ( [ volume_id ] ) <EOL> if volumes : <EOL> return volumes [ <NUM_LIT:0> ] <EOL> def _volume_compatible_with_resource_definition ( self , volume ) : <EOL> return ( <EOL> ( not self . resource . size or self . resource . size == volume . size ) , <EOL> ( not self . resource . availability_zone or self . resource . availability_zone == volume . zone ) , <EOL> ( self . resource . snapshot_id == volume . snapshot_id ) <EOL> ) <EOL> def _find_snapshot ( self , name ) : <EOL> snapshots = self . ec2 . get_all_snapshots ( filters = { "<STR_LIT>" : name } ) <EOL> if snapshots : <EOL> snapshots . sort ( cmp = lambda x , y : cmp ( y . start_time , x . start_time ) ) <EOL> return snapshots [ <NUM_LIT:0> ] <EOL> return None <EOL> def _create_volume ( self , snapshot_id , size , availability_zone , name , timeout ) : <EOL> """<STR_LIT>""" <EOL> self . log . debug ( "<STR_LIT>" , snapshot_id , size , availability_zone , name , timeout ) <EOL> if snapshot_id and not snapshot_id . startswith ( '<STR_LIT>' ) : <EOL> sid = self . _find_snapshot ( snapshot_id ) <EOL> if not sid and self . resource . snapshot_required : <EOL> raise Fail ( "<STR_LIT>" % snapshot_id ) <EOL> snapshot_id = sid <EOL> availability_zone = availability_zone or self . resource . env . config . aws . availability_zone <EOL> vol = self . ec2 . create_volume ( size , availability_zone , snapshot_id ) <EOL> self . log . info ( "<STR_LIT>" , name , vol . id , "<STR_LIT>" % snapshot_id if snapshot_id else "<STR_LIT>" ) <EOL> start_time = time . time ( ) <EOL> end_time = start_time + timeout if timeout else <NUM_LIT:0> <EOL> while ( not timeout ) or ( time . time ( ) < end_time ) : <EOL> if vol . update ( ) in ( '<STR_LIT>' , '<STR_LIT>' ) : <EOL> break <EOL> time . sleep ( <NUM_LIT:1> ) <EOL> if name : <EOL> vol . add_tag ( '<STR_LIT:Name>' , name ) <EOL> try : <EOL> del self . resource . env . config . aws . resources . _volumes <EOL> except AttributeError : <EOL> pass <EOL> return vol <EOL> def _attach_volume ( self , vol , instance_id , device , timeout ) : <EOL> """<STR_LIT>""" <EOL> self . log . info ( "<STR_LIT>" % ( vol . id , device ) ) <EOL> vol . attach ( instance_id , device ) <EOL> start_time = time . time ( ) <EOL> end_time = start_time + timeout if timeout else <NUM_LIT:0> <EOL> attached = False <EOL> while ( not timeout ) or ( time . time ( ) < end_time ) : <EOL> if vol . update ( ) != "<STR_LIT>" : <EOL> if vol . attachment_state ( ) == "<STR_LIT>" : <EOL> if vol . attach_data . instance_id == instance_id : <EOL> self . log . info ( "<STR_LIT>" % self ) <EOL> attached = True <EOL> break <EOL> else : <EOL> raise Fail ( "<STR_LIT>" % ( vol . attach_data . instance_id , instance_id ) ) <EOL> else : <EOL> self . log . debug ( "<STR_LIT>" % vol . status ) <EOL> else : <EOL> raise Fail ( "<STR_LIT>" % ( self , vol . id ) ) <EOL> time . sleep ( <NUM_LIT:3> ) <EOL> if attached : <EOL> while ( not timeout ) or ( time . time ( ) < end_time ) : <EOL> if os . path . exists ( self . resource . device ) : <EOL> return <EOL> time . sleep ( <NUM_LIT:1> ) <EOL> raise Fail ( "<STR_LIT>" % ( time . time ( ) - start_time ) ) <EOL> @ property <EOL> def ec2 ( self ) : <EOL> return self . resource . env . config . aws . resources . ec2 </s>
