def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" try: action_args = self.get_action_args(request.environ) action = action_args.pop('action', None) deserialized_request = self.deserialize_request(request) action_args.update(deserialized_request) except exception.InvalidContentType: msg = _("Unsupported Content-Type") return webob.exc.HTTPUnsupportedMediaType(explanation=msg) except exception.MalformedRequestBody: msg = _("Malformed request body") return webob.exc.HTTPBadRequest(explanation=msg) action_result = self.execute_action(action, request, **action_args) try: response = webob.Response(request=request) self.dispatch(self.serializer, action, response, action_result) return response # return unserializable result (typically a webob exc) except Exception: try: err_body = action_result.get_unserialized_body() self.serializer.default(action_result, err_body) except Exception: LOG.warning(_LW("Unable to serialize exception response")) return action_result
def load_paste_app(app_name=None): """Builds and returns a WSGI app from a paste config file. We assume the last config file specified in the supplied ConfigOpts object is the paste config file. :param app_name: name of the application to load :raises RuntimeError when config file cannot be located or application cannot be loaded from config file """ if app_name is None: app_name = CONF.prog app_name += _get_deployment_flavor() conf_file = _get_deployment_config_file() if conf_file is None: raise RuntimeError(_("Unable to locate config file")) try: LOG.debug("Loading %(app_name)s from %(conf_file)s" % {'conf_file': conf_file, 'app_name': app_name}) app = wsgi.paste_deploy_app(conf_file, app_name, cfg.CONF) return app except (LookupError, ImportError) as e: msg = _("Unable to load %(app_name)s from configuration file " "%(conf_file)s. \nGot: %(e)r") % \ {'conf_file': conf_file, 'app_name': app_name, 'e': e} LOG.error(msg) raise RuntimeError(msg)
def _validate_auth_url(self, auth_url): """Validate auth_url to ensure it can be used.""" if not auth_url: raise exc.HTTPBadRequest(_("Request missing required header " "X-Auth-Url")) allowed = cfg.CONF.auth_password.allowed_auth_uris if auth_url not in allowed: raise exc.HTTPUnauthorized(_('Header X-Auth-Url "%s" not ' "an allowed endpoint") % auth_url) return True
def _get_socket(host, port, backlog): info = socket.getaddrinfo( host, port, socket.AF_UNSPEC, socket.SOCK_STREAM )[0] family = info[0] bind_addr = info[-1] sock = None retry_until = time.time() + 30 while not sock and time.time() < retry_until: try: sock = eventlet.listen(bind_addr, backlog=backlog, family=family) if sslutils.is_enabled(CONF): sock = sslutils.wrap(CONF, sock) except socket.error as err: if err.args[0] != errno.EADDRINUSE: raise if not sock: raise RuntimeError(_( "Could not bind to %(host)s:%(port)s " "after trying for 30 seconds") % {'host': host, 'port': port}) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # sockets can hang around forever without keepalive sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # This option isn't available in the OS X version of eventlet if hasattr(socket, 'TCP_KEEPIDLE'): sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, CONF.tcp_keepidle) return sock
def deprecated(self, msg, *args, **kwargs): """Call this method when a deprecated feature is used. If the system is configured for fatal deprecations then the message is logged at the 'critical' level and :class:`DeprecatedConfig` will be raised. Otherwise, the message will be logged (once) at the 'warn' level. :param kwargs: :param args: :param msg: :raises: :class:`DeprecatedConfig` if the system is configured for fatal deprecations. """ stdmsg = _("Deprecated: %s") % msg if CONF.fatal_deprecations: self.critical(stdmsg, *args, **kwargs) raise DeprecatedConfig(msg=stdmsg) # Using a list because a tuple with dict can't be stored in a set. sent_args = self._deprecated_messages_sent.setdefault(msg, list()) if args in sent_args: # Already logged this message, so don't log it again. return sent_args.append(args) self.warn(stdmsg, *args, **kwargs)
def validate(request, body): """ Validate the given cookbook :param request: request context :param body: a json with deployment parameters :return : a json file with process results """ body = body or {} if len(body) < 1: raise exc.HTTPBadRequest(_("No action specified")) try: cookbook = body['cookbook'] image = body['image'] except KeyError: raise exc.HTTPBadRequest(_("Insufficient payload")) LOG.info(_LI('Processing Request for cookbook %s, image %s' % (cookbook, image))) res = ValidateEngine().validate_chef_cookbook(cookbook, image, request) return res
def _get_deployment_config_file(): """Retrieve the deployment_config_file config item, formatted as an absolute pathname. """ path = CONF.paste_deploy.config_file if CONF.debug: return os.path.abspath(os.path.join(CONF.config_dir, path)) if not path: path = _get_paste_config_path() if not path: msg = _("Unable to locate paste config file for %s.") % CONF.prog raise RuntimeError(msg) return os.path.abspath(path)
def run_deploy(self, cookbook): """ Run cookbook deployment :param cookbook: cookbook to deploy :return msg: dictionary with results and state """ try: # launch execution cmd_launch = CONF.clients_chef.cmd_launch resp_launch = self.execute_command(cmd_launch) msg = { 'success': True, 'response': resp_launch } LOG.debug(_("Launch result: %s") % resp_launch) if resp_launch is None or "FATAL" in resp_launch: msg['success'] = False except Exception as e: self.remove_container(self.container) LOG.error(_LW("Cookbook deployment exception %s" % e)) raise CookbookDeploymentException(cookbook=cookbook) return msg
def run_install(self, cookbook): """Run download and install command :param cookbook: cookbook to process :return msg: operation result """ try: cmd_install = CONF.clients_chef.cmd_install.format(cookbook) resp_install = self.execute_command(cmd_install) msg = { 'success': True, 'response': resp_install } for line in resp_install.splitlines(): if "ERROR" in line: msg['success'] = False LOG.debug(_("Install result: %s") % resp_install) except Exception as e: self.remove_container(self.container) LOG.error(_LW("Chef install exception: %s" % e)) raise CookbookInstallException(cookbook=cookbook) return msg
def run_test(self, cookbook): """ Test cookbook syntax :param cookbook: cookbook to test :return msg: dictionary with results and state """ try: cmd_test = CONF.clients_chef.cmd_test.format(cookbook) resp_test = self.execute_command(cmd_test) msg = { 'success': True, 'response': resp_test } for line in resp_test.splitlines(): if "ERROR" in line: msg['success'] = False LOG.debug(_("Test result: %s") % resp_test) except Exception as e: self.remove_container(self.container) LOG.error(_LW("Cookbook syntax exception %s" % e)) raise CookbookSyntaxException(cookbook=cookbook) return msg
def test_all_remote_exceptions(self): for name, obj in inspect.getmembers( validator_exc, lambda x: inspect.isclass(x) and issubclass(x, validator_exc.OpenstackException)): if '__init__' in obj.__dict__: if obj == validator_exc.OpenstackException: # # manually ignore baseclass continue elif obj == validator_exc.Error: error = obj('Error') elif obj == validator_exc.NotFound: error = obj() elif obj == validator_exc.ResourceFailure: exc = validator_exc.Error(_('Error')) error = obj(exc, None, 'CREATE') elif obj == validator_exc.ResourcePropertyConflict: error = obj('%s' % 'a test prop') else: continue self.remote_exception_helper(name, error) continue if hasattr(obj, 'msg_fmt'): kwargs = {} spec_names = re.findall('%\((\w+)\)([cdeEfFgGinorsxX])', obj.msg_fmt) for key, convtype in spec_names: if convtype == 'r' or convtype == 's': kwargs[key] = '"' + key + '"' else: # this is highly unlikely raise Exception("test needs additional conversion" " type added due to %s exception" " using '%c' specifier" % (obj, convtype)) error = obj(**kwargs) self.remote_exception_helper(name, error)
def _find_facility_from_conf(): facility_names = logging.handlers.SysLogHandler.facility_names facility = getattr(logging.handlers.SysLogHandler, CONF.syslog_log_facility, None) if facility is None and CONF.syslog_log_facility in facility_names: facility = facility_names.get(CONF.syslog_log_facility) if facility is None: valid_facilities = facility_names.keys() consts = ['LOG_AUTH', 'LOG_AUTHPRIV', 'LOG_CRON', 'LOG_DAEMON', 'LOG_FTP', 'LOG_KERN', 'LOG_LPR', 'LOG_MAIL', 'LOG_NEWS', 'LOG_AUTH', 'LOG_SYSLOG', 'LOG_USER', 'LOG_UUCP', 'LOG_LOCAL0', 'LOG_LOCAL1', 'LOG_LOCAL2', 'LOG_LOCAL3', 'LOG_LOCAL4', 'LOG_LOCAL5', 'LOG_LOCAL6', 'LOG_LOCAL7'] valid_facilities.extend(consts) raise TypeError(_('syslog facility must be one of: %s') % ', '.join("'%s'" % fac for fac in valid_facilities)) return facility
socket_opts = [ cfg.IntOpt('tcp_keepidle', default=600, help="Sets the value of TCP_KEEPIDLE in seconds for each " "server socket. Not supported on OS X."), ] CONF = cfg.CONF CONF.register_opts(socket_opts) LOG = logging.getLogger(__name__) # Local ip/port binding options bind_opts = [ cfg.StrOpt('bind_host', default=socket.gethostname(), help=_('Name of the engine node.')), cfg.StrOpt('bind_port', default=4041, help=_('Listening port of the engine node.')), ] CONF.register_cli_opts(bind_opts) # Paste/Deploy server options paste_deploy_group = cfg.OptGroup('paste_deploy') paste_deploy_opts = [ cfg.StrOpt('config_file', default="api-paste.ini", help=_("The API config file to use.")), cfg.StrOpt('flavor', help=_("The flavor to use.")) ] CONF.register_group(paste_deploy_group) CONF.register_opts(paste_deploy_opts, group='paste_deploy')
def default(request): try: return {'body': jsonutils.loads(request.body)} except ValueError: raise exception.MalformedRequestBody( reason=_("cannot understand JSON"))