<s> import hashlib <EOL> import hmac <EOL> import httplib2 <EOL> from neutron_lib import constants <EOL> from oslo_config import cfg <EOL> from oslo_log import log as logging <EOL> import oslo_messaging <EOL> from oslo_service import loopingcall <EOL> from oslo_utils import encodeutils <EOL> import six <EOL> import six . moves . urllib . parse as urlparse <EOL> import webob <EOL> from neutron . _i18n import _ , _LE , _LW <EOL> from neutron . agent . linux import utils as agent_utils <EOL> from neutron . agent . metadata import config <EOL> from neutron . agent import rpc as agent_rpc <EOL> from neutron . common import constants as n_const <EOL> from neutron . common import rpc as n_rpc <EOL> from neutron . common import topics <EOL> from neutron . common import utils <EOL> from neutron import context <EOL> from neutron . openstack . common . cache import cache <EOL> LOG = logging . getLogger ( __name__ ) <EOL> MODE_MAP = { <EOL> config . USER_MODE : <NUM_LIT> , <EOL> config . GROUP_MODE : <NUM_LIT> , <EOL> config . ALL_MODE : <NUM_LIT> , <EOL> } <EOL> class MetadataPluginAPI ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , topic ) : <EOL> target = oslo_messaging . Target ( <EOL> topic = topic , <EOL> namespace = n_const . RPC_NAMESPACE_METADATA , <EOL> version = '<STR_LIT:1.0>' ) <EOL> self . client = n_rpc . get_client ( target ) <EOL> def get_ports ( self , context , filters ) : <EOL> cctxt = self . client . prepare ( ) <EOL> return cctxt . call ( context , '<STR_LIT>' , filters = filters ) <EOL> class MetadataProxyHandler ( object ) : <EOL> def __init__ ( self , conf ) : <EOL> self . conf = conf <EOL> if self . conf . cache_url : <EOL> self . _cache = cache . get_cache ( self . conf . cache_url ) <EOL> else : <EOL> self . _cache = False <EOL> self . plugin_rpc = MetadataPluginAPI ( topics . PLUGIN ) <EOL> self . context = context . get_admin_context_without_session ( ) <EOL> @ webob . dec . wsgify ( RequestClass = webob . Request ) <EOL> def __call__ ( self , req ) : <EOL> try : <EOL> LOG . debug ( "<STR_LIT>" , req ) <EOL> instance_id , tenant_id = self . _get_instance_and_tenant_id ( req ) <EOL> if instance_id : <EOL> return self . _proxy_request ( instance_id , tenant_id , req ) <EOL> else : <EOL> return webob . exc . HTTPNotFound ( ) <EOL> except Exception : <EOL> LOG . exception ( _LE ( "<STR_LIT>" ) ) <EOL> msg = _ ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> explanation = six . text_type ( msg ) <EOL> return webob . exc . HTTPInternalServerError ( explanation = explanation ) <EOL> def _get_ports_from_server ( self , router_id = None , ip_address = None , <EOL> networks = None ) : <EOL> """<STR_LIT>""" <EOL> filters = self . _get_port_filters ( router_id , ip_address , networks ) <EOL> return self . plugin_rpc . get_ports ( self . context , filters ) <EOL> def _get_port_filters ( self , router_id = None , ip_address = None , <EOL> networks = None ) : <EOL> filters = { } <EOL> if router_id : <EOL> filters [ '<STR_LIT>' ] = [ router_id ] <EOL> filters [ '<STR_LIT>' ] = constants . ROUTER_INTERFACE_OWNERS <EOL> if ip_address : <EOL> filters [ '<STR_LIT>' ] = { '<STR_LIT>' : [ ip_address ] } <EOL> if networks : <EOL> filters [ '<STR_LIT>' ] = networks <EOL> return filters <EOL> @ utils . cache_method_results <EOL> def _get_router_networks ( self , router_id ) : <EOL> """<STR_LIT>""" <EOL> internal_ports = self . _get_ports_from_server ( router_id = router_id ) <EOL> return tuple ( p [ '<STR_LIT>' ] for p in internal_ports ) <EOL> @ utils . cache_method_results <EOL> def _get_ports_for_remote_address ( self , remote_address , networks ) : <EOL> """<STR_LIT>""" <EOL> return self . _get_ports_from_server ( networks = networks , <EOL> ip_address = remote_address ) <EOL> def _get_ports ( self , remote_address , network_id = None , router_id = None ) : <EOL> """<STR_LIT>""" <EOL> if network_id : <EOL> networks = ( network_id , ) <EOL> elif router_id : <EOL> networks = self . _get_router_networks ( router_id ) <EOL> else : <EOL> raise TypeError ( _ ( "<STR_LIT>" <EOL> "<STR_LIT>" ) ) <EOL> return self . _get_ports_for_remote_address ( remote_address , networks ) <EOL> def _get_instance_and_tenant_id ( self , req ) : <EOL> remote_address = req . headers . get ( '<STR_LIT>' ) <EOL> network_id = req . headers . get ( '<STR_LIT>' ) <EOL> router_id = req . headers . get ( '<STR_LIT>' ) <EOL> ports = self . _get_ports ( remote_address , network_id , router_id ) <EOL> if len ( ports ) == <NUM_LIT:1> : <EOL> return ports [ <NUM_LIT:0> ] [ '<STR_LIT>' ] , ports [ <NUM_LIT:0> ] [ '<STR_LIT>' ] <EOL> return None , None <EOL> def _proxy_request ( self , instance_id , tenant_id , req ) : <EOL> headers = { <EOL> '<STR_LIT>' : req . headers . get ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : instance_id , <EOL> '<STR_LIT>' : tenant_id , <EOL> '<STR_LIT>' : self . _sign_instance_id ( instance_id ) <EOL> } <EOL> nova_ip_port = '<STR_LIT>' % ( self . conf . nova_metadata_ip , <EOL> self . conf . nova_metadata_port ) <EOL> url = urlparse . urlunsplit ( ( <EOL> self . conf . nova_metadata_protocol , <EOL> nova_ip_port , <EOL> req . path_info , <EOL> req . query_string , <EOL> '<STR_LIT>' ) ) <EOL> h = httplib2 . Http ( <EOL> ca_certs = self . conf . auth_ca_cert , <EOL> disable_ssl_certificate_validation = self . conf . nova_metadata_insecure <EOL> ) <EOL> if self . conf . nova_client_cert and self . conf . nova_client_priv_key : <EOL> h . add_certificate ( self . conf . nova_client_priv_key , <EOL> self . conf . nova_client_cert , <EOL> nova_ip_port ) <EOL> resp , content = h . request ( url , method = req . method , headers = headers , <EOL> body = req . body ) <EOL> if resp . status == <NUM_LIT:200> : <EOL> LOG . debug ( str ( resp ) ) <EOL> req . response . content_type = resp [ '<STR_LIT>' ] <EOL> req . response . body = content <EOL> return req . response <EOL> elif resp . status == <NUM_LIT> : <EOL> LOG . warning ( _LW ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> ) ) <EOL> return webob . exc . HTTPForbidden ( ) <EOL> elif resp . status == <NUM_LIT> : <EOL> return webob . exc . HTTPBadRequest ( ) <EOL> elif resp . status == <NUM_LIT> : <EOL> return webob . exc . HTTPNotFound ( ) <EOL> elif resp . status == <NUM_LIT> : <EOL> return webob . exc . HTTPConflict ( ) <EOL> elif resp . status == <NUM_LIT> : <EOL> msg = _ ( <EOL> '<STR_LIT>' <EOL> ) <EOL> LOG . warning ( msg ) <EOL> explanation = six . text_type ( msg ) <EOL> return webob . exc . HTTPInternalServerError ( explanation = explanation ) <EOL> else : <EOL> raise Exception ( _ ( '<STR_LIT>' ) % resp . status ) <EOL> def _sign_instance_id ( self , instance_id ) : <EOL> secret = self . conf . metadata_proxy_shared_secret <EOL> secret = encodeutils . to_utf8 ( secret ) <EOL> instance_id = encodeutils . to_utf8 ( instance_id ) <EOL> return hmac . new ( secret , instance_id , hashlib . sha256 ) . hexdigest ( ) <EOL> class UnixDomainMetadataProxy ( object ) : <EOL> def __init__ ( self , conf ) : <EOL> self . conf = conf <EOL> agent_utils . ensure_directory_exists_without_file ( <EOL> cfg . CONF . metadata_proxy_socket ) <EOL> self . _init_state_reporting ( ) <EOL> def _init_state_reporting ( self ) : <EOL> self . context = context . get_admin_context_without_session ( ) <EOL> self . state_rpc = agent_rpc . PluginReportStateAPI ( topics . REPORTS ) <EOL> self . agent_state = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:host>' : cfg . CONF . host , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : { <EOL> '<STR_LIT>' : cfg . CONF . metadata_proxy_socket , <EOL> '<STR_LIT>' : cfg . CONF . nova_metadata_ip , <EOL> '<STR_LIT>' : cfg . CONF . nova_metadata_port , <EOL> '<STR_LIT>' : cfg . CONF . AGENT . log_agent_heartbeats , <EOL> } , <EOL> '<STR_LIT>' : True , <EOL> '<STR_LIT>' : constants . AGENT_TYPE_METADATA } <EOL> report_interval = cfg . CONF . AGENT . report_interval <EOL> if report_interval : <EOL> self . heartbeat = loopingcall . FixedIntervalLoopingCall ( <EOL> self . _report_state ) <EOL> self . heartbeat . start ( interval = report_interval ) <EOL> def _report_state ( self ) : <EOL> try : <EOL> self . state_rpc . report_state ( <EOL> self . context , <EOL> self . agent_state , <EOL> use_call = self . agent_state . get ( '<STR_LIT>' ) ) <EOL> except AttributeError : <EOL> LOG . warning ( _LW ( '<STR_LIT>' <EOL> '<STR_LIT>' ) ) <EOL> self . heartbeat . stop ( ) <EOL> return <EOL> except Exception : <EOL> LOG . exception ( _LE ( "<STR_LIT>" ) ) <EOL> return <EOL> self . agent_state . pop ( '<STR_LIT>' , None ) <EOL> def _get_socket_mode ( self ) : <EOL> mode = self . conf . metadata_proxy_socket_mode <EOL> if mode == config . DEDUCE_MODE : <EOL> user = self . conf . metadata_proxy_user <EOL> if ( not user or user == '<STR_LIT:0>' or user == '<STR_LIT:root>' <EOL> or agent_utils . is_effective_user ( user ) ) : <EOL> mode = config . USER_MODE <EOL> else : <EOL> group = self . conf . metadata_proxy_group <EOL> if not group or agent_utils . is_effective_group ( group ) : <EOL> mode = config . GROUP_MODE <EOL> else : <EOL> mode = config . ALL_MODE <EOL> return MODE_MAP [ mode ] <EOL> def run ( self ) : <EOL> server = agent_utils . UnixDomainWSGIServer ( '<STR_LIT>' ) <EOL> server . start ( MetadataProxyHandler ( self . conf ) , <EOL> self . conf . metadata_proxy_socket , <EOL> workers = self . conf . metadata_workers , <EOL> backlog = self . conf . metadata_backlog , <EOL> mode = self . _get_socket_mode ( ) ) <EOL> server . wait ( ) </s>
