<s> import collections <EOL> import gc <EOL> import json <EOL> import platform <EOL> import socket <EOL> import sys <EOL> import traceback <EOL> import jinja2 <EOL> from oslo_utils import reflection <EOL> from oslo_utils import strutils <EOL> from oslo_utils import timeutils <EOL> import six <EOL> import stevedore <EOL> import webob . dec <EOL> import webob . exc <EOL> import webob . response <EOL> try : <EOL> import greenlet <EOL> except ImportError : <EOL> greenlet = None <EOL> from oslo_middleware import base <EOL> def _find_objects ( t ) : <EOL> return [ o for o in gc . get_objects ( ) if isinstance ( o , t ) ] <EOL> def _expand_template ( contents , params ) : <EOL> tpl = jinja2 . Template ( source = contents , <EOL> undefined = jinja2 . StrictUndefined ) <EOL> return tpl . render ( ** params ) <EOL> class Healthcheck ( base . ConfigurableMiddleware ) : <EOL> """<STR_LIT>""" <EOL> NAMESPACE = "<STR_LIT>" <EOL> HEALTHY_TO_STATUS_CODES = { <EOL> True : webob . exc . HTTPOk . code , <EOL> False : webob . exc . HTTPServiceUnavailable . code , <EOL> } <EOL> HEAD_HEALTHY_TO_STATUS_CODES = { <EOL> True : webob . exc . HTTPNoContent . code , <EOL> False : webob . exc . HTTPServiceUnavailable . code , <EOL> } <EOL> PLAIN_RESPONSE_TEMPLATE = """<STR_LIT>""" <EOL> HTML_RESPONSE_TEMPLATE = """<STR_LIT>""" <EOL> def __init__ ( self , application , conf ) : <EOL> super ( Healthcheck , self ) . __init__ ( application ) <EOL> self . _path = conf . get ( '<STR_LIT:path>' , '<STR_LIT>' ) <EOL> self . _show_details = strutils . bool_from_string ( conf . get ( '<STR_LIT>' ) ) <EOL> self . _backend_names = [ ] <EOL> backends = conf . get ( '<STR_LIT>' ) <EOL> if backends : <EOL> self . _backend_names = backends . split ( '<STR_LIT:U+002C>' ) <EOL> self . _backends = stevedore . NamedExtensionManager ( <EOL> self . NAMESPACE , self . _backend_names , <EOL> name_order = True , invoke_on_load = True , <EOL> invoke_args = ( conf , ) ) <EOL> self . _accept_to_functor = collections . OrderedDict ( [ <EOL> ( '<STR_LIT>' , self . _make_text_response ) , <EOL> ( '<STR_LIT>' , self . _make_html_response ) , <EOL> ( '<STR_LIT:application/json>' , self . _make_json_response ) , <EOL> ] ) <EOL> self . _accept_order = tuple ( six . iterkeys ( self . _accept_to_functor ) ) <EOL> self . _default_accept = '<STR_LIT>' <EOL> @ staticmethod <EOL> def _get_threadstacks ( ) : <EOL> threadstacks = [ ] <EOL> try : <EOL> active_frames = sys . _current_frames ( ) <EOL> except AttributeError : <EOL> pass <EOL> else : <EOL> buf = six . StringIO ( ) <EOL> for stack in six . itervalues ( active_frames ) : <EOL> traceback . print_stack ( stack , file = buf ) <EOL> threadstacks . append ( buf . getvalue ( ) ) <EOL> buf . seek ( <NUM_LIT:0> ) <EOL> buf . truncate ( ) <EOL> return threadstacks <EOL> @ staticmethod <EOL> def _get_greenstacks ( ) : <EOL> greenstacks = [ ] <EOL> if greenlet is not None : <EOL> buf = six . StringIO ( ) <EOL> for gt in _find_objects ( greenlet . greenlet ) : <EOL> traceback . print_stack ( gt . gr_frame , file = buf ) <EOL> greenstacks . append ( buf . getvalue ( ) ) <EOL> buf . seek ( <NUM_LIT:0> ) <EOL> buf . truncate ( ) <EOL> return greenstacks <EOL> @ staticmethod <EOL> def _pretty_json_dumps ( contents ) : <EOL> return json . dumps ( contents , indent = <NUM_LIT:4> , sort_keys = True ) <EOL> @ staticmethod <EOL> def _are_results_healthy ( results ) : <EOL> for result in results : <EOL> if not result . available : <EOL> return False <EOL> return True <EOL> def _make_text_response ( self , results , healthy ) : <EOL> params = { <EOL> '<STR_LIT>' : [ result . reason for result in results ] , <EOL> '<STR_LIT>' : self . _show_details , <EOL> } <EOL> body = _expand_template ( self . PLAIN_RESPONSE_TEMPLATE , params ) <EOL> return ( body . strip ( ) , '<STR_LIT>' ) <EOL> def _make_json_response ( self , results , healthy ) : <EOL> if self . _show_details : <EOL> body = { <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : sys . version , <EOL> '<STR_LIT>' : str ( timeutils . utcnow ( ) ) , <EOL> '<STR_LIT>' : platform . platform ( ) , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : gc . get_count ( ) , <EOL> '<STR_LIT>' : gc . get_threshold ( ) , <EOL> } , <EOL> } <EOL> reasons = [ ] <EOL> for result in results : <EOL> reasons . append ( { <EOL> '<STR_LIT>' : result . reason , <EOL> '<STR_LIT>' : result . details or '<STR_LIT>' , <EOL> '<STR_LIT:class>' : reflection . get_class_name ( result , <EOL> fully_qualified = False ) , <EOL> } ) <EOL> body [ '<STR_LIT>' ] = reasons <EOL> body [ '<STR_LIT>' ] = self . _get_greenstacks ( ) <EOL> body [ '<STR_LIT>' ] = self . _get_threadstacks ( ) <EOL> else : <EOL> body = { <EOL> '<STR_LIT>' : [ result . reason for result in results ] , <EOL> '<STR_LIT>' : False , <EOL> } <EOL> return ( self . _pretty_json_dumps ( body ) , '<STR_LIT:application/json>' ) <EOL> def _make_head_response ( self , results , healthy ) : <EOL> return ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> def _make_html_response ( self , results , healthy ) : <EOL> try : <EOL> hostname = socket . gethostname ( ) <EOL> except socket . error : <EOL> hostname = None <EOL> translated_results = [ ] <EOL> for result in results : <EOL> translated_results . append ( { <EOL> '<STR_LIT>' : result . details or '<STR_LIT>' , <EOL> '<STR_LIT>' : result . reason , <EOL> '<STR_LIT:class>' : reflection . get_class_name ( result , <EOL> fully_qualified = False ) , <EOL> } ) <EOL> params = { <EOL> '<STR_LIT>' : healthy , <EOL> '<STR_LIT>' : hostname , <EOL> '<STR_LIT>' : translated_results , <EOL> '<STR_LIT>' : self . _show_details , <EOL> '<STR_LIT>' : str ( timeutils . utcnow ( ) ) , <EOL> '<STR_LIT>' : sys . version , <EOL> '<STR_LIT>' : platform . platform ( ) , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : gc . get_count ( ) , <EOL> '<STR_LIT>' : gc . get_threshold ( ) , <EOL> } , <EOL> '<STR_LIT>' : self . _get_threadstacks ( ) , <EOL> '<STR_LIT>' : self . _get_threadstacks ( ) , <EOL> } <EOL> body = _expand_template ( self . HTML_RESPONSE_TEMPLATE , params ) <EOL> return ( body . strip ( ) , '<STR_LIT>' ) <EOL> @ webob . dec . wsgify <EOL> def process_request ( self , req ) : <EOL> if req . path != self . _path : <EOL> return None <EOL> results = [ ext . obj . healthcheck ( req . server_port ) <EOL> for ext in self . _backends ] <EOL> healthy = self . _are_results_healthy ( results ) <EOL> if req . method == "<STR_LIT>" : <EOL> functor = self . _make_head_response <EOL> status = self . HEAD_HEALTHY_TO_STATUS_CODES [ healthy ] <EOL> else : <EOL> status = self . HEALTHY_TO_STATUS_CODES [ healthy ] <EOL> accept_type = req . accept . best_match ( self . _accept_order ) <EOL> if not accept_type : <EOL> accept_type = self . _default_accept <EOL> functor = self . _accept_to_functor [ accept_type ] <EOL> body , content_type = functor ( results , healthy ) <EOL> return webob . response . Response ( status = status , body = body , <EOL> content_type = content_type ) </s>
