def __exit__(self, ex_type, ex_value, ex_traceback): if not ex_value: return True if isinstance(ex_value, exception.Forbidden): raise Fault( webob.exc.HTTPForbidden(explanation=ex_value.format_message())) elif isinstance(ex_value, exception.VersionNotFoundForAPIMethod): raise elif isinstance(ex_value, exception.Invalid): raise Fault( exception.ConvertedException( code=ex_value.code, explanation=ex_value.format_message())) elif isinstance(ex_value, TypeError): exc_info = (ex_type, ex_value, ex_traceback) LOG.error(_LE('Exception handling resource: %s'), ex_value, exc_info=exc_info) raise Fault(webob.exc.HTTPBadRequest()) elif isinstance(ex_value, Fault): LOG.info(_LI("Fault thrown: %s"), ex_value) raise ex_value elif isinstance(ex_value, webob.exc.HTTPException): LOG.info(_LI("HTTP exception thrown: %s"), ex_value) raise Fault(ex_value) # We didn't handle the exception return False
def _error(self, inner, req): LOG.exception(_LE("Caught error: %s"), six.text_type(inner)) safe = getattr(inner, 'safe', False) headers = getattr(inner, 'headers', None) status = getattr(inner, 'code', 500) if status is None: status = 500 msg_dict = dict(url=req.url, status=status) LOG.info(_LI("%(url)s returned with HTTP %(status)d"), msg_dict) outer = self.status_to_type(status) if headers: outer.headers = headers # NOTE(johannes): We leave the explanation empty here on # purpose. It could possibly have sensitive information # that should not be returned back to the user. See # bugs 868360 and 874472 # NOTE(eglynn): However, it would be over-conservative and # inconsistent with the EC2 API to hide every exception, # including those that are safe to expose, see bug 1021373 if safe: user_locale = req.best_match_language() inner_msg = translate(inner.message, user_locale) outer.explanation = '%s: %s' % (inner.__class__.__name__, inner_msg) return wsgi.Fault(outer)
def wait(self): """Block, until the server has stopped. Waits on the server's eventlet to finish, then returns. :returns: None """ try: if self._server is not None: self._pool.waitall() self._server.wait() except greenlet.GreenletExit: LOG.info(_LI("WSGI server has stopped."))
def stop(self): """Stop this server. This is not a very nice action, as currently the method by which a server is stopped is by killing its eventlet. :returns: None """ LOG.info(_LI("Stopping WSGI server.")) if self._server is not None: # Resize pool to stop new requests from being processed self._pool.resize(0) self._server.kill()
def __init__(self, name, app, host='0.0.0.0', port=0, pool_size=None, protocol=eventlet.wsgi.HttpProtocol, backlog=128, use_ssl=False, max_url_len=None): """Initialize, but do not start, a WSGI server. :param name: Pretty name for logging. :param app: The WSGI application to serve. :param host: IP address to serve the application. :param port: Port number to server the application. :param pool_size: Maximum number of eventlets to spawn concurrently. :param backlog: Maximum number of queued connections. :param max_url_len: Maximum length of permitted URLs. :returns: None :raises: fastrunner.exception.InvalidInput """ # Allow operators to customize http requests max header line size. eventlet.wsgi.MAX_HEADER_LINE = CONF.max_header_line self.name = name self.app = app self._server = None self._protocol = protocol self.pool_size = pool_size or self.default_pool_size self._pool = eventlet.GreenPool(self.pool_size) self._logger = logging.getLogger("fastrunner.%s.wsgi.server" % self.name) self._use_ssl = use_ssl self._max_url_len = max_url_len self.client_socket_timeout = CONF.client_socket_timeout or None if backlog < 1: raise exception.InvalidInput( reason=_('The backlog must be more than 0')) bind_addr = (host, port) # TODO(dims): eventlet's green dns/socket module does not actually # support IPv6 in getaddrinfo(). We need to get around this in the # future or monitor upstream for a fix try: info = socket.getaddrinfo(bind_addr[0], bind_addr[1], socket.AF_UNSPEC, socket.SOCK_STREAM)[0] family = info[0] bind_addr = info[-1] except Exception: family = socket.AF_INET try: self._socket = eventlet.listen(bind_addr, family, backlog=backlog) except EnvironmentError: LOG.error(_LE("Could not bind to %(host)s:%(port)s"), { 'host': host, 'port': port }) raise (self.host, self.port) = self._socket.getsockname()[0:2] LOG.info(_LI("%(name)s listening on %(host)s:%(port)s"), { 'name': self.name, 'host': self.host, 'port': self.port })
def __init__(self, init_only=None, v3mode=False): # TODO(cyeoh): bp v3-api-extension-framework. Currently load # all extensions but eventually should be able to exclude # based on a config file # TODO(oomichi): We can remove v3mode argument after moving all v3 APIs # to v2.1. def _check_load_extension(ext): if (self.init_only is None or ext.obj.alias in self.init_only) and isinstance( ext.obj, extensions.V21APIExtensionBase): return self._register_extension(ext) return False if not CONF.osapi_v21.enabled: LOG.info(_LI("V2.1 API has been disabled by configuration")) LOG.warning(_LW("In the M release you must run the v2.1 API.")) return if (CONF.osapi_v21.extensions_blacklist or CONF.osapi_v21.extensions_whitelist): LOG.warning( _LW('In the M release you must run all of the API. ' 'The concept of API extensions will be removed from ' 'the codebase to ensure there is a single Compute API.')) self.init_only = init_only LOG.debug("v21 API Extension Blacklist: %s", CONF.osapi_v21.extensions_blacklist) LOG.debug("v21 API Extension Whitelist: %s", CONF.osapi_v21.extensions_whitelist) in_blacklist_and_whitelist = set( CONF.osapi_v21.extensions_whitelist).intersection( CONF.osapi_v21.extensions_blacklist) if len(in_blacklist_and_whitelist) != 0: LOG.warning(_LW("Extensions in both blacklist and whitelist: %s"), list(in_blacklist_and_whitelist)) self.api_extension_manager = stevedore.enabled.EnabledExtensionManager( namespace=self.api_extension_namespace(), check_func=_check_load_extension, invoke_on_load=True, invoke_kwds={"extension_info": self.loaded_extension_info}) if v3mode: mapper = PlainMapper() else: mapper = ProjectMapper() self.resources = {} # NOTE(cyeoh) Core API support is rewritten as extensions # but conceptually still have core if list(self.api_extension_manager): # NOTE(cyeoh): Stevedore raises an exception if there are # no plugins detected. I wonder if this is a bug. self._register_resources_check_inherits(mapper) self.api_extension_manager.map(self._register_controllers) missing_core_extensions = self.get_missing_core_extensions( self.loaded_extension_info.get_extensions().keys()) #if not self.init_only and missing_core_extensions: # LOG.critical(_LC("Missing core API extensions: %s"), # missing_core_extensions) # raise exception.CoreAPIMissing( # missing_apis=missing_core_extensions) LOG.info(_LI("Loaded extensions: %s"), sorted(self.loaded_extension_info.get_extensions().keys())) super(APIRouterV21, self).__init__(mapper)