<s> import argparse <EOL> import datetime <EOL> import json <EOL> import math <EOL> import sys <EOL> import operator <EOL> import os <EOL> sys . path . append ( os . environ . get ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> import usage_audit <EOL> from stacktach import datetime_to_decimal as dt <EOL> from stacktach import models <EOL> from stacktach import stacklog <EOL> class TenantManager ( object ) : <EOL> def __init__ ( self ) : <EOL> self . _types = None <EOL> def __enter__ ( self ) : <EOL> return self <EOL> def __exit__ ( self , exc_type , exc_value , traceback ) : <EOL> return False <EOL> @ property <EOL> def type_names ( self ) : <EOL> if self . _types is None : <EOL> self . _types = set ( ) <EOL> for t in models . TenantType . objects . all ( ) : <EOL> self . _types . add ( t . name ) <EOL> return self . _types <EOL> def get_tenant_info ( self , tenant_id ) : <EOL> try : <EOL> tenant = models . TenantInfo . objects . get ( tenant = tenant_id ) <EOL> tenant_info = dict ( <EOL> tenant = tenant_id , <EOL> account_name = tenant . name ) <EOL> ttypes = dict ( ) <EOL> for t in tenant . types . all ( ) : <EOL> ttypes [ t . name ] = t . value <EOL> except models . TenantInfo . DoesNotExist : <EOL> tenant_info = dict ( <EOL> tenant = tenant_id , <EOL> account_name = '<STR_LIT>' ) <EOL> ttypes = dict ( ) <EOL> for t in self . type_names : <EOL> ttypes [ t ] = '<STR_LIT>' <EOL> tenant_info [ '<STR_LIT>' ] = ttypes <EOL> return tenant_info <EOL> class InstanceHoursReport ( object ) : <EOL> FLAVOR_CLASS_WEIGHTS = dict ( standard = <NUM_LIT:1.0> ) <EOL> def __init__ ( self , tenant_manager , time = None , period_length = '<STR_LIT>' ) : <EOL> if time is None : <EOL> time = datetime . datetime . utcnow ( ) <EOL> self . start , self . end = usage_audit . get_previous_period ( time , period_length ) <EOL> self . tenant_manager = tenant_manager <EOL> self . flavor_cache = dict ( ) <EOL> self . clear ( ) <EOL> def clear ( self ) : <EOL> self . count = <NUM_LIT:0> <EOL> self . unit_hours = <NUM_LIT:0.0> <EOL> self . by_flavor = dict ( ) <EOL> self . by_flavor_class = dict ( ) <EOL> self . by_tenant = dict ( ) <EOL> self . by_type = dict ( ) <EOL> for name in self . tenant_manager . type_names : <EOL> self . by_tenant [ name ] = dict ( ) <EOL> self . by_type [ name ] = dict ( ) <EOL> def _get_verified_exists ( self ) : <EOL> start = dt . dt_to_decimal ( self . start ) <EOL> end = dt . dt_to_decimal ( self . end ) <EOL> return models . InstanceExists . objects . filter ( <EOL> status = models . InstanceExists . VERIFIED , <EOL> audit_period_beginning__gte = start , <EOL> audit_period_beginning__lte = end , <EOL> audit_period_ending__gte = start , <EOL> audit_period_ending__lte = end ) <EOL> def _get_instance_hours ( self , exist ) : <EOL> if ( exist . deleted_at is None ) or ( exist . deleted_at > exist . audit_period_ending ) : <EOL> end = exist . audit_period_ending <EOL> else : <EOL> end = exist . deleted_at <EOL> if exist . launched_at > exist . audit_period_beginning : <EOL> start = exist . launched_at <EOL> else : <EOL> start = exist . audit_period_beginning <EOL> return math . ceil ( ( end - start ) / <NUM_LIT> ) <EOL> def _get_flavor_info ( self , exist ) : <EOL> flavor = exist . instance_flavor_id <EOL> if flavor not in self . flavor_cache : <EOL> if '<STR_LIT:->' in flavor : <EOL> flavor_class , n = flavor . split ( '<STR_LIT:->' , <NUM_LIT:1> ) <EOL> else : <EOL> flavor_class = '<STR_LIT>' <EOL> try : <EOL> payload = json . loads ( exist . raw . json ) [ <NUM_LIT:1> ] [ '<STR_LIT>' ] <EOL> except Exception : <EOL> print "<STR_LIT>" % exist . id <EOL> raise <EOL> flavor_name = payload [ '<STR_LIT>' ] <EOL> flavor_size = payload [ '<STR_LIT>' ] <EOL> weight = self . FLAVOR_CLASS_WEIGHTS . get ( flavor_class , <NUM_LIT:1.0> ) <EOL> flavor_units = ( flavor_size / <NUM_LIT> ) * weight <EOL> self . flavor_cache [ flavor ] = ( flavor , flavor_name , flavor_class , flavor_units ) <EOL> return self . flavor_cache [ flavor ] <EOL> def add_type_hours ( self , type_name , type_value , unit_hours ) : <EOL> if type_value not in self . by_type [ type_name ] : <EOL> self . by_type [ type_name ] [ type_value ] = dict ( count = <NUM_LIT:0> , unit_hours = <NUM_LIT:0.0> ) <EOL> cts = self . by_type [ type_name ] [ type_value ] <EOL> cts [ '<STR_LIT:count>' ] += <NUM_LIT:1> <EOL> cts [ '<STR_LIT>' ] += unit_hours <EOL> cts [ '<STR_LIT>' ] = ( float ( cts [ '<STR_LIT:count>' ] ) / self . count ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = ( cts [ '<STR_LIT>' ] / self . unit_hours ) * <NUM_LIT:100> <EOL> def add_flavor_class_hours ( self , flavor_class , unit_hours ) : <EOL> if flavor_class not in self . by_flavor_class : <EOL> self . by_flavor_class [ flavor_class ] = dict ( count = <NUM_LIT:0> , unit_hours = <NUM_LIT:0.0> ) <EOL> cts = self . by_flavor_class [ flavor_class ] <EOL> cts [ '<STR_LIT:count>' ] += <NUM_LIT:1> <EOL> cts [ '<STR_LIT>' ] += unit_hours <EOL> cts [ '<STR_LIT>' ] = ( float ( cts [ '<STR_LIT:count>' ] ) / self . count ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = ( cts [ '<STR_LIT>' ] / self . unit_hours ) * <NUM_LIT:100> <EOL> def add_flavor_hours ( self , flavor , flavor_name , unit_hours ) : <EOL> if flavor not in self . by_flavor : <EOL> self . by_flavor [ flavor ] = dict ( count = <NUM_LIT:0> , unit_hours = <NUM_LIT:0.0> ) <EOL> cts = self . by_flavor [ flavor ] <EOL> cts [ '<STR_LIT:count>' ] += <NUM_LIT:1> <EOL> cts [ '<STR_LIT>' ] += unit_hours <EOL> cts [ '<STR_LIT>' ] = ( float ( cts [ '<STR_LIT:count>' ] ) / self . count ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = ( cts [ '<STR_LIT>' ] / self . unit_hours ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = flavor_name <EOL> def add_tenant_hours ( self , tenant_info , unit_hours ) : <EOL> tenant = tenant_info [ '<STR_LIT>' ] <EOL> cts = dict ( count = <NUM_LIT:0> , unit_hours = <NUM_LIT:0.0> ) <EOL> for tname , tvalue in tenant_info [ '<STR_LIT>' ] . items ( ) : <EOL> if tvalue not in self . by_tenant [ tname ] : <EOL> self . by_tenant [ tname ] [ tvalue ] = dict ( ) <EOL> if tenant not in self . by_tenant [ tname ] [ tvalue ] : <EOL> self . by_tenant [ tname ] [ tvalue ] [ tenant ] = cts <EOL> cts = self . by_tenant [ tname ] [ tvalue ] [ tenant ] <EOL> cts [ tname ] = tvalue <EOL> cts [ '<STR_LIT:count>' ] += <NUM_LIT:1> <EOL> cts [ '<STR_LIT>' ] += unit_hours <EOL> cts [ '<STR_LIT>' ] = ( float ( cts [ '<STR_LIT:count>' ] ) / self . count ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = ( cts [ '<STR_LIT>' ] / self . unit_hours ) * <NUM_LIT:100> <EOL> cts [ '<STR_LIT>' ] = tenant <EOL> cts [ '<STR_LIT>' ] = tenant_info [ '<STR_LIT>' ] <EOL> def compile_hours ( self ) : <EOL> exists = self . _get_verified_exists ( ) <EOL> self . count = exists . count ( ) <EOL> with self . tenant_manager as tenant_manager : <EOL> for exist in exists : <EOL> hours = self . _get_instance_hours ( exist ) <EOL> flavor , flavor_name , flavor_class , flavor_units = self . _get_flavor_info ( exist ) <EOL> tenant_info = tenant_manager . get_tenant_info ( exist . tenant ) <EOL> unit_hours = hours * flavor_units <EOL> self . unit_hours += unit_hours <EOL> self . add_flavor_hours ( flavor , flavor_name , unit_hours ) <EOL> self . add_flavor_class_hours ( flavor_class , unit_hours ) <EOL> for tname , tvalue in tenant_info [ '<STR_LIT>' ] . items ( ) : <EOL> self . add_type_hours ( tname , tvalue , unit_hours ) <EOL> self . add_tenant_hours ( tenant_info , unit_hours ) <EOL> def top_hundred ( self , key ) : <EOL> def th ( d ) : <EOL> top = dict ( ) <EOL> for t , customers in d . iteritems ( ) : <EOL> top [ t ] = sorted ( customers . values ( ) , key = operator . itemgetter ( key ) , reverse = True ) [ : <NUM_LIT:100> ] <EOL> return top <EOL> top_hundred = dict ( ) <EOL> for type_name , tenants in self . by_tenant . iteritems ( ) : <EOL> top_hundred [ type_name ] = th ( tenants ) <EOL> return top_hundred <EOL> def generate_json ( self ) : <EOL> report = dict ( total_instance_count = self . count , <EOL> total_unit_hours = self . unit_hours , <EOL> flavor = self . by_flavor , <EOL> flavor_class = self . by_flavor_class , <EOL> top_hundred_by_count = self . top_hundred ( '<STR_LIT:count>' ) , <EOL> top_hundred_by_unit_hours = self . top_hundred ( '<STR_LIT>' ) ) <EOL> for ttype , stats in self . by_type . iteritems ( ) : <EOL> report [ ttype ] = stats <EOL> return json . dumps ( report ) <EOL> def store ( self , json_report ) : <EOL> report = models . JsonReport ( <EOL> json = json_report , <EOL> created = dt . dt_to_decimal ( datetime . datetime . utcnow ( ) ) , <EOL> period_start = self . start , <EOL> period_end = self . end , <EOL> version = <NUM_LIT:1> , <EOL> name = '<STR_LIT>' ) <EOL> report . save ( ) <EOL> def valid_datetime ( d ) : <EOL> try : <EOL> t = datetime . datetime . strptime ( d , "<STR_LIT>" ) <EOL> return t <EOL> except Exception , e : <EOL> raise argparse . ArgumentTypeError ( <EOL> "<STR_LIT>" % d ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> parser = argparse . ArgumentParser ( '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , <EOL> choices = [ '<STR_LIT>' , '<STR_LIT>' ] , default = '<STR_LIT>' ) <EOL> parser . add_argument ( '<STR_LIT>' , <EOL> help = "<STR_LIT>" , <EOL> type = valid_datetime , default = None ) <EOL> parser . add_argument ( '<STR_LIT>' , <EOL> help = "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> default = False , action = "<STR_LIT:store_true>" ) <EOL> args = parser . parse_args ( ) <EOL> stacklog . set_default_logger_name ( '<STR_LIT>' ) <EOL> parent_logger = stacklog . get_logger ( '<STR_LIT>' , is_parent = True ) <EOL> log_listener = stacklog . LogListener ( parent_logger ) <EOL> log_listener . start ( ) <EOL> tenant_manager = TenantManager ( ) <EOL> report = InstanceHoursReport ( <EOL> tenant_manager , <EOL> time = args . utcdatetime , <EOL> period_length = args . period_length ) <EOL> report . compile_hours ( ) <EOL> json = report . generate_json ( ) <EOL> if not args . store : <EOL> print json <EOL> else : <EOL> report . store ( json ) </s>
