<s> import collections <EOL> import copy <EOL> import pprint <EOL> import time <EOL> from neutron_lib import constants <EOL> from oslo_log import log as logging <EOL> from oslo_utils import importutils <EOL> from neutron . api . rpc . callbacks import exceptions <EOL> LOG = logging . getLogger ( __name__ ) <EOL> VERSIONS_TTL = <NUM_LIT> <EOL> NON_REPORTING_AGENT_TYPES = [ constants . AGENT_TYPE_OVS , <EOL> constants . AGENT_TYPE_NIC_SWITCH ] <EOL> def _import_resources ( ) : <EOL> return importutils . import_module ( '<STR_LIT>' ) <EOL> AgentConsumer = collections . namedtuple ( '<STR_LIT>' , [ '<STR_LIT>' , <EOL> '<STR_LIT:host>' ] ) <EOL> AgentConsumer . __repr__ = lambda self : '<STR_LIT>' % self <EOL> class ResourceConsumerTracker ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _versions = self . _get_local_resource_versions ( ) <EOL> self . _versions_by_consumer = collections . defaultdict ( dict ) <EOL> self . _needs_recalculation = False <EOL> def _get_local_resource_versions ( self ) : <EOL> resources = _import_resources ( ) <EOL> local_resource_versions = collections . defaultdict ( set ) <EOL> for resource_type , version in ( <EOL> resources . LOCAL_RESOURCE_VERSIONS . items ( ) ) : <EOL> local_resource_versions [ resource_type ] . add ( version ) <EOL> return local_resource_versions <EOL> def _set_version ( self , consumer , resource_type , version ) : <EOL> """<STR_LIT>""" <EOL> self . _versions [ resource_type ] . add ( version ) <EOL> consumer_versions = self . _versions_by_consumer [ consumer ] <EOL> prev_version = consumer_versions . get ( resource_type , None ) <EOL> if version : <EOL> consumer_versions [ resource_type ] = version <EOL> else : <EOL> consumer_versions . pop ( resource_type , None ) <EOL> if prev_version != version : <EOL> self . _needs_recalculation = True <EOL> LOG . debug ( "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" , <EOL> { '<STR_LIT>' : resource_type , <EOL> '<STR_LIT:version>' : version , <EOL> '<STR_LIT>' : prev_version , <EOL> '<STR_LIT>' : consumer } ) <EOL> def set_versions ( self , consumer , versions ) : <EOL> """<STR_LIT>""" <EOL> for resource_type , resource_version in versions . items ( ) : <EOL> self . _set_version ( consumer , resource_type , <EOL> resource_version ) <EOL> if versions : <EOL> self . _cleanup_removed_versions ( consumer , versions ) <EOL> else : <EOL> self . _handle_no_set_versions ( consumer ) <EOL> def _cleanup_removed_versions ( self , consumer , versions ) : <EOL> """<STR_LIT>""" <EOL> prev_resource_types = set ( <EOL> self . _versions_by_consumer [ consumer ] . keys ( ) ) <EOL> cur_resource_types = set ( versions . keys ( ) ) <EOL> removed_resource_types = prev_resource_types - cur_resource_types <EOL> for resource_type in removed_resource_types : <EOL> self . _set_version ( consumer , resource_type , None ) <EOL> def _handle_no_set_versions ( self , consumer ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( consumer , AgentConsumer ) : <EOL> if consumer . agent_type in NON_REPORTING_AGENT_TYPES : <EOL> resources = _import_resources ( ) <EOL> self . _versions_by_consumer [ consumer ] = { <EOL> resources . QOS_POLICY : '<STR_LIT:1.0>' } <EOL> self . _versions [ resources . QOS_POLICY ] . add ( '<STR_LIT:1.0>' ) <EOL> return <EOL> if self . _versions_by_consumer [ consumer ] : <EOL> self . _needs_recalculation = True <EOL> self . _versions_by_consumer [ consumer ] = { } <EOL> def get_resource_versions ( self , resource_type ) : <EOL> """<STR_LIT>""" <EOL> if self . _needs_recalculation : <EOL> self . _recalculate_versions ( ) <EOL> self . _needs_recalculation = False <EOL> return copy . copy ( self . _versions [ resource_type ] ) <EOL> def report ( self ) : <EOL> """<STR_LIT>""" <EOL> format = lambda versions : pprint . pformat ( dict ( versions ) , indent = <NUM_LIT:4> ) <EOL> debug_dict = { '<STR_LIT>' : format ( self . _versions ) , <EOL> '<STR_LIT>' : format ( self . _versions_by_consumer ) } <EOL> LOG . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' , debug_dict ) <EOL> def _recalculate_versions ( self ) : <EOL> """<STR_LIT>""" <EOL> versions = self . _get_local_resource_versions ( ) <EOL> for versions_dict in self . _versions_by_consumer . values ( ) : <EOL> for res_type , res_version in versions_dict . items ( ) : <EOL> versions [ res_type ] . add ( res_version ) <EOL> self . _versions = versions <EOL> class CachedResourceConsumerTracker ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _consumer_versions_callback = None <EOL> self . _expires_at = <NUM_LIT:0> <EOL> self . _versions = ResourceConsumerTracker ( ) <EOL> def _update_consumer_versions ( self ) : <EOL> if self . _consumer_versions_callback : <EOL> new_tracker = ResourceConsumerTracker ( ) <EOL> self . _consumer_versions_callback ( new_tracker ) <EOL> self . _versions = new_tracker <EOL> self . _versions . report ( ) <EOL> else : <EOL> raise exceptions . VersionsCallbackNotFound ( ) <EOL> def _check_expiration ( self ) : <EOL> if time . time ( ) > self . _expires_at : <EOL> self . _update_consumer_versions ( ) <EOL> self . _expires_at = time . time ( ) + VERSIONS_TTL <EOL> def set_consumer_versions_callback ( self , callback ) : <EOL> self . _consumer_versions_callback = callback <EOL> def get_resource_versions ( self , resource_type ) : <EOL> self . _check_expiration ( ) <EOL> return self . _versions . get_resource_versions ( resource_type ) <EOL> def update_versions ( self , consumer , resource_versions ) : <EOL> self . _versions . set_versions ( consumer , resource_versions ) <EOL> def report ( self ) : <EOL> self . _check_expiration ( ) <EOL> self . _versions . report ( ) <EOL> _cached_version_tracker = None <EOL> def _get_cached_tracker ( ) : <EOL> global _cached_version_tracker <EOL> if not _cached_version_tracker : <EOL> _cached_version_tracker = CachedResourceConsumerTracker ( ) <EOL> return _cached_version_tracker <EOL> def set_consumer_versions_callback ( callback ) : <EOL> """<STR_LIT>""" <EOL> _get_cached_tracker ( ) . set_consumer_versions_callback ( callback ) <EOL> def get_resource_versions ( resource_type ) : <EOL> """<STR_LIT>""" <EOL> return _get_cached_tracker ( ) . get_resource_versions ( resource_type ) <EOL> def update_versions ( consumer , resource_versions ) : <EOL> """<STR_LIT>""" <EOL> _get_cached_tracker ( ) . update_versions ( consumer , resource_versions ) <EOL> def report ( ) : <EOL> """<STR_LIT>""" <EOL> _get_cached_tracker ( ) . report ( ) </s>
