<s> import datetime <EOL> import iso8601 <EOL> from oslo_utils import timeutils <EOL> import six <EOL> import six . moves . urllib . parse as urlparse <EOL> from webob import exc <EOL> from nova . api . openstack import extensions <EOL> from nova . api . openstack import wsgi <EOL> from nova import exception <EOL> from nova . i18n import _ <EOL> from nova import objects <EOL> ALIAS = "<STR_LIT>" <EOL> authorize = extensions . os_compute_authorizer ( ALIAS ) <EOL> def parse_strtime ( dstr , fmt ) : <EOL> try : <EOL> return timeutils . parse_strtime ( dstr , fmt ) <EOL> except ( TypeError , ValueError ) as e : <EOL> raise exception . InvalidStrTime ( reason = six . text_type ( e ) ) <EOL> class SimpleTenantUsageController ( wsgi . Controller ) : <EOL> def _hours_for ( self , instance , period_start , period_stop ) : <EOL> launched_at = instance . launched_at <EOL> terminated_at = instance . terminated_at <EOL> if terminated_at is not None : <EOL> if not isinstance ( terminated_at , datetime . datetime ) : <EOL> terminated_at = timeutils . parse_isotime ( terminated_at ) <EOL> if launched_at is not None : <EOL> if not isinstance ( launched_at , datetime . datetime ) : <EOL> launched_at = timeutils . parse_isotime ( launched_at ) <EOL> if terminated_at and terminated_at < period_start : <EOL> return <NUM_LIT:0> <EOL> if launched_at and launched_at > period_stop : <EOL> return <NUM_LIT:0> <EOL> if launched_at : <EOL> start = max ( launched_at , period_start ) <EOL> if terminated_at : <EOL> stop = min ( period_stop , terminated_at ) <EOL> else : <EOL> stop = period_stop <EOL> dt = stop - start <EOL> return dt . total_seconds ( ) / <NUM_LIT> <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def _get_flavor ( self , context , instance , flavors_cache ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> return instance . get_flavor ( ) <EOL> except exception . NotFound : <EOL> if not instance . deleted : <EOL> raise <EOL> flavor_type = instance . instance_type_id <EOL> if flavor_type in flavors_cache : <EOL> return flavors_cache [ flavor_type ] <EOL> try : <EOL> flavor_ref = objects . Flavor . get_by_id ( context , flavor_type ) <EOL> flavors_cache [ flavor_type ] = flavor_ref <EOL> except exception . FlavorNotFound : <EOL> flavor_ref = None <EOL> return flavor_ref <EOL> def _tenant_usages_for_period ( self , context , period_start , <EOL> period_stop , tenant_id = None , detailed = True ) : <EOL> instances = objects . InstanceList . get_active_by_window_joined ( <EOL> context , period_start , period_stop , tenant_id , <EOL> expected_attrs = [ '<STR_LIT>' ] ) <EOL> rval = { } <EOL> flavors = { } <EOL> for instance in instances : <EOL> info = { } <EOL> info [ '<STR_LIT>' ] = self . _hours_for ( instance , <EOL> period_start , <EOL> period_stop ) <EOL> flavor = self . _get_flavor ( context , instance , flavors ) <EOL> if not flavor : <EOL> info [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> else : <EOL> info [ '<STR_LIT>' ] = flavor . name <EOL> info [ '<STR_LIT>' ] = instance . uuid <EOL> info [ '<STR_LIT:name>' ] = instance . display_name <EOL> info [ '<STR_LIT>' ] = instance . memory_mb <EOL> info [ '<STR_LIT>' ] = instance . root_gb + instance . ephemeral_gb <EOL> info [ '<STR_LIT>' ] = instance . vcpus <EOL> info [ '<STR_LIT>' ] = instance . project_id <EOL> info [ '<STR_LIT>' ] = timeutils . normalize_time ( instance . launched_at ) <EOL> info [ '<STR_LIT>' ] = ( <EOL> timeutils . normalize_time ( instance . terminated_at ) if <EOL> instance . terminated_at else None ) <EOL> if info [ '<STR_LIT>' ] : <EOL> info [ '<STR_LIT:state>' ] = '<STR_LIT>' <EOL> else : <EOL> info [ '<STR_LIT:state>' ] = instance . vm_state <EOL> now = timeutils . utcnow ( ) <EOL> if info [ '<STR_LIT:state>' ] == '<STR_LIT>' : <EOL> delta = info [ '<STR_LIT>' ] - info [ '<STR_LIT>' ] <EOL> else : <EOL> delta = now - info [ '<STR_LIT>' ] <EOL> info [ '<STR_LIT>' ] = int ( delta . total_seconds ( ) ) <EOL> if info [ '<STR_LIT>' ] not in rval : <EOL> summary = { } <EOL> summary [ '<STR_LIT>' ] = info [ '<STR_LIT>' ] <EOL> if detailed : <EOL> summary [ '<STR_LIT>' ] = [ ] <EOL> summary [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> summary [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> summary [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> summary [ '<STR_LIT>' ] = <NUM_LIT:0> <EOL> summary [ '<STR_LIT:start>' ] = timeutils . normalize_time ( period_start ) <EOL> summary [ '<STR_LIT>' ] = timeutils . normalize_time ( period_stop ) <EOL> rval [ info [ '<STR_LIT>' ] ] = summary <EOL> summary = rval [ info [ '<STR_LIT>' ] ] <EOL> summary [ '<STR_LIT>' ] += info [ '<STR_LIT>' ] * info [ '<STR_LIT>' ] <EOL> summary [ '<STR_LIT>' ] += info [ '<STR_LIT>' ] * info [ '<STR_LIT>' ] <EOL> summary [ '<STR_LIT>' ] += ( info [ '<STR_LIT>' ] * <EOL> info [ '<STR_LIT>' ] ) <EOL> summary [ '<STR_LIT>' ] += info [ '<STR_LIT>' ] <EOL> if detailed : <EOL> summary [ '<STR_LIT>' ] . append ( info ) <EOL> return rval . values ( ) <EOL> def _parse_datetime ( self , dtstr ) : <EOL> if not dtstr : <EOL> value = timeutils . utcnow ( ) <EOL> elif isinstance ( dtstr , datetime . datetime ) : <EOL> value = dtstr <EOL> else : <EOL> for fmt in [ "<STR_LIT>" , <EOL> "<STR_LIT>" , <EOL> "<STR_LIT>" ] : <EOL> try : <EOL> value = parse_strtime ( dtstr , fmt ) <EOL> break <EOL> except exception . InvalidStrTime : <EOL> pass <EOL> else : <EOL> msg = _ ( "<STR_LIT>" ) <EOL> raise exception . InvalidStrTime ( reason = msg ) <EOL> if value . utcoffset ( ) is None : <EOL> value = value . replace ( tzinfo = iso8601 . iso8601 . Utc ( ) ) <EOL> return value <EOL> def _get_datetime_range ( self , req ) : <EOL> qs = req . environ . get ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> env = urlparse . parse_qs ( qs ) <EOL> period_start = self . _parse_datetime ( env . get ( '<STR_LIT:start>' , [ None ] ) [ <NUM_LIT:0> ] ) <EOL> period_stop = self . _parse_datetime ( env . get ( '<STR_LIT:end>' , [ None ] ) [ <NUM_LIT:0> ] ) <EOL> if not period_start < period_stop : <EOL> msg = _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) <EOL> raise exc . HTTPBadRequest ( explanation = msg ) <EOL> detailed = env . get ( '<STR_LIT>' , [ '<STR_LIT:0>' ] ) [ <NUM_LIT:0> ] == '<STR_LIT:1>' <EOL> return ( period_start , period_stop , detailed ) <EOL> @ extensions . expected_errors ( <NUM_LIT> ) <EOL> def index ( self , req ) : <EOL> """<STR_LIT>""" <EOL> context = req . environ [ '<STR_LIT>' ] <EOL> authorize ( context , action = '<STR_LIT:list>' ) <EOL> try : <EOL> ( period_start , period_stop , detailed ) = self . _get_datetime_range ( <EOL> req ) <EOL> except exception . InvalidStrTime as e : <EOL> raise exc . HTTPBadRequest ( explanation = e . format_message ( ) ) <EOL> now = timeutils . parse_isotime ( timeutils . utcnow ( ) . isoformat ( ) ) <EOL> if period_stop > now : <EOL> period_stop = now <EOL> usages = self . _tenant_usages_for_period ( context , <EOL> period_start , <EOL> period_stop , <EOL> detailed = detailed ) <EOL> return { '<STR_LIT>' : usages } <EOL> @ extensions . expected_errors ( <NUM_LIT> ) <EOL> def show ( self , req , id ) : <EOL> """<STR_LIT>""" <EOL> tenant_id = id <EOL> context = req . environ [ '<STR_LIT>' ] <EOL> authorize ( context , action = '<STR_LIT>' , target = { '<STR_LIT>' : tenant_id } ) <EOL> try : <EOL> ( period_start , period_stop , ignore ) = self . _get_datetime_range ( <EOL> req ) <EOL> except exception . InvalidStrTime as e : <EOL> raise exc . HTTPBadRequest ( explanation = e . format_message ( ) ) <EOL> now = timeutils . parse_isotime ( timeutils . utcnow ( ) . isoformat ( ) ) <EOL> if period_stop > now : <EOL> period_stop = now <EOL> usage = self . _tenant_usages_for_period ( context , <EOL> period_start , <EOL> period_stop , <EOL> tenant_id = tenant_id , <EOL> detailed = True ) <EOL> if len ( usage ) : <EOL> usage = list ( usage ) [ <NUM_LIT:0> ] <EOL> else : <EOL> usage = { } <EOL> return { '<STR_LIT>' : usage } <EOL> class SimpleTenantUsage ( extensions . V21APIExtensionBase ) : <EOL> """<STR_LIT>""" <EOL> name = "<STR_LIT>" <EOL> alias = ALIAS <EOL> version = <NUM_LIT:1> <EOL> def get_resources ( self ) : <EOL> resources = [ ] <EOL> res = extensions . ResourceExtension ( ALIAS , <EOL> SimpleTenantUsageController ( ) ) <EOL> resources . append ( res ) <EOL> return resources <EOL> def get_controller_extensions ( self ) : <EOL> return [ ] </s>
