def validate_integer(value, name, min_value=None, max_value=None): """Make sure that value is a valid integer, potentially within range. :param value: the value of the integer :param name: the name of the integer :param min_length: the min_length of the integer :param max_length: the max_length of the integer :returns: integer """ try: value = int(value) except (TypeError, ValueError, UnicodeEncodeError): raise webob.exc.HTTPBadRequest(explanation=( _('%s must be an integer.') % name)) if min_value is not None and value < min_value: raise webob.exc.HTTPBadRequest( explanation=(_('%(value_name)s must be >= %(min_value)d') % {'value_name': name, 'min_value': min_value})) if max_value is not None and value > max_value: raise webob.exc.HTTPBadRequest( explanation=(_('%(value_name)s must be <= %(max_value)d') % {'value_name': name, 'max_value': max_value})) return value
def __call__(self, environ, start_response): r"""Subclasses will probably want to implement __call__ like this: @webob.dec.wsgify(RequestClass=Request) def __call__(self, req): # Any of the following objects work as responses: # Option 1: simple string res = 'message\n' # Option 2: a nicely formatted HTTP exception page res = exc.HTTPForbidden(explanation='Nice try') # Option 3: a webob Response object (in case you need to play with # headers, or you want to be treated like an iterable) res = Response(); res.app_iter = open('somefile') # Option 4: any wsgi app to be run next res = self.application # Option 5: you can get a Response object for a wsgi app, too, to # play with headers etc res = req.get_response(self.application) # You can then just return your response... return res # ... or set req.response and return None. req.response = res See the end of http://pythonpaste.org/webob/modules/dec.html for more info. """ raise NotImplementedError(_('You must implement __call__'))
def db_sync(engine, version=None): """Migrate the database to `version` or the most recent version.""" if version is not None and int(version) < db_version(engine): raise exception.CoriolisException( _("Cannot migrate to lower schema version.")) return migration.db_sync(engine, version=version)
def action_peek_json(body): """Determine action to invoke.""" try: decoded = jsonutils.loads(body) except ValueError: msg = _("cannot understand JSON") raise exception.MalformedRequestBody(reason=msg) # Make sure there's exactly one key... if len(decoded) != 1: msg = _("too many body keys") raise exception.MalformedRequestBody(reason=msg) # Return the action and the decoded body... return list(decoded.keys())[0]
def _check_string_length(value, name, min_length=0, max_length=None): """Check the length of specified string. :param value: the value of the string :param name: the name of the string :param min_length: the min_length of the string :param max_length: the max_length of the string """ if not isinstance(value, six.string_types): msg = _("%s is not a string or unicode") % name raise exception.InvalidInput(message=msg) if len(value) < min_length: msg = _("%(name)s has a minimum character requirement of " "%(min_length)s.") % {'name': name, 'min_length': min_length} raise exception.InvalidInput(message=msg) if max_length and len(value) > max_length: msg = _("%(name)s has more than %(max_length)s " "characters.") % {'name': name, 'max_length': max_length} raise exception.InvalidInput(message=msg)
def assert_valid_body(body, entity_name): # NOTE: After v1 api is deprecated need to merge 'is_valid_body' and # 'assert_valid_body' in to one method. Right now it is not # possible to modify 'is_valid_body' to raise exception because # in case of V1 api when 'is_valid_body' return False, # 'HTTPUnprocessableEntity' exception is getting raised and in # V2 api 'HTTPBadRequest' exception is getting raised. if not Controller.is_valid_body(body, entity_name): raise webob.exc.HTTPBadRequest( explanation=_("Missing required element '%s' in " "request body.") % entity_name)
def __call__(self, req): user = req.headers.get('X_USER') user = req.headers.get('X_USER_ID', user) if user is None: LOG.debug("Neither X_USER_ID nor X_USER found in request") return webob.exc.HTTPUnauthorized() # get the roles roles = [r.strip() for r in req.headers.get('X_ROLE', '').split(',')] if 'X_TENANT_ID' in req.headers: # This is the new header since Keystone went to ID/Name tenant = req.headers['X_TENANT_ID'] else: # This is for legacy compatibility tenant = req.headers['X_TENANT'] project_name = req.headers.get('X_TENANT_NAME') project_domain_name = req.headers.get('X-Project-Domain-Name') user_domain_name = req.headers.get('X-User-Domain-Name') req_id = req.environ.get(request_id.ENV_REQUEST_ID) # TODO(alexpilotti): Check why it's not str if isinstance(req_id, bytes): req_id = req_id.decode() # Get the auth token auth_token = req.headers.get('X_AUTH_TOKEN') # Build a context, including the auth_token... remote_address = req.remote_addr service_catalog = None if req.headers.get('X_SERVICE_CATALOG') is not None: try: catalog_header = req.headers.get('X_SERVICE_CATALOG') service_catalog = jsonutils.loads(catalog_header) except ValueError: raise webob.exc.HTTPInternalServerError( explanation=_('Invalid service catalog json.')) ctx = context.RequestContext(user, tenant, project_name=project_name, project_domain=project_domain_name, user_domain=user_domain_name, roles=roles, auth_token=auth_token, remote_address=remote_address, service_catalog=service_catalog, request_id=req_id) req.environ['coriolis.context'] = ctx return self.application
def __init__(self, ext_mgr=None): if ext_mgr is None: if self.ExtensionManager: ext_mgr = self.ExtensionManager() else: raise exception.CoriolisException( _("Must specify an ExtensionManager class")) mapper = ProjectMapper() self.resources = {} self._setup_routes(mapper, ext_mgr) self._setup_ext_routes(mapper, ext_mgr) self._setup_extensions(ext_mgr) super(APIRouter, self).__init__(mapper)
def _error(self, inner, req): LOG.exception(_LE("Caught error: %(type)s %(error)s"), {'type': type(inner), 'error': 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 if safe: msg = (inner.msg if isinstance(inner, exception.CoriolisException) else six.text_type(inner)) params = {'exception': inner.__class__.__name__, 'explanation': msg} outer.explanation = _('%(exception)s: %(explanation)s') % params return wsgi.Fault(outer)
class MalformedRequestBody(CoriolisException): message = _("Malformed message body: %(reason)s") code = 400 safe = True
class FloatingIPPoolNotFound(NotFound): message = _("Floating IP pool \"%(pool_name)s\" could not be found.")
class VolumeSnapshotNotFound(NotFound): message = _("Volume snapshot \"%(snapshot_id)s\" could not be found.")
class DiskStorageMappingNotFound(NotFound): message = _('No storage mapping for disk with ID "%(id)s" could be found.')
class ImageNotFound(NotFound): message = _("Image \"%(image_name)s\" could not be found.")
class OSMorphingToolsNotFound(NotFound): message = _("Couldn't find any morphing tools for this OS.")
class InstanceNotFound(NotFound): message = _("Instance \"%(instance_name)s\" could not be found.")
class APITimeout(APIException): message = _("Timeout while requesting %(service)s API.")
class InvalidReplicaState(Invalid): message = _("Invalid replica state: %(reason)s")
class InvalidActionTasksExecutionState(Invalid): message = _("Invalid tasks execution state: %(reason)s")
def _process_stack(self, request, action, action_args, content_type, body, accept): """Implement the processing stack.""" # Get the implementing method try: meth, extensions = self.get_method(request, action, content_type, body) except (AttributeError, TypeError): return Fault(webob.exc.HTTPNotFound()) except KeyError as ex: msg = _("There is no such action: %s") % ex.args[0] return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Now, deserialize the request body... try: if content_type: contents = self.deserialize(meth, content_type, body) else: contents = {} except exception.InvalidContentType: msg = _("Unsupported Content-Type") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) except exception.MalformedRequestBody: msg = _("Malformed request body") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Update the action args action_args.update(contents) project_id = action_args.pop("project_id", None) context = request.environ.get('coriolis.context') if (context and project_id and (project_id != context.tenant)): msg = _("Malformed request url") return Fault(webob.exc.HTTPBadRequest(explanation=msg)) # Run pre-processing extensions response, post = self.pre_process_extensions(extensions, request, action_args) if not response: try: with ResourceExceptionHandler(): action_result = self.dispatch(meth, request, action_args) except Fault as ex: response = ex if not response: # No exceptions; convert action_result into a # ResponseObject resp_obj = None if type(action_result) is dict or action_result is None: resp_obj = ResponseObject(action_result) elif isinstance(action_result, ResponseObject): resp_obj = action_result else: response = action_result # Run post-processing extensions if resp_obj: _set_request_id_header(request, resp_obj) # Do a preserialize to set up the response object serializers = getattr(meth, 'wsgi_serializers', {}) resp_obj._bind_method_serializers(serializers) if hasattr(meth, 'wsgi_code'): resp_obj._default_code = meth.wsgi_code resp_obj.preserialize(accept, self.default_serializers) # Process post-processing extensions response = self.post_process_extensions(post, resp_obj, request, action_args) if resp_obj and not response: response = resp_obj.serialize(request, accept, self.default_serializers) try: msg_dict = dict(url=request.url, status=response.status_int) msg = _LI("%(url)s returned with HTTP %(status)d") except AttributeError as e: msg_dict = dict(url=request.url, e=e) msg = _LI("%(url)s returned a fault: %(e)s") LOG.info(msg, msg_dict) return response
def _from_json(self, datastring): try: return jsonutils.loads(datastring) except ValueError: msg = _("cannot understand JSON") raise exception.MalformedRequestBody(reason=msg)
class InvalidMigrationState(Invalid): message = _("Invalid migration state: %(reason)s")
class InvalidInput(Invalid): message = _("Invalid input received: %(reason)s")
class ServiceUnavailable(Invalid): message = _("Service is unavailable at this time.")
class InvalidContentType(Invalid): message = _("Invalid content type %(content_type)s.")
class NotFound(CoriolisException): message = _("Resource could not be found.") code = 404 safe = True
class InvalidHost(Invalid): message = _("Invalid host: %(reason)s")
class FileNotFound(NotFound): message = _("File %(file_path)s could not be found.")
class SameDestination(Invalid): message = _("Origin and destination cannot be the same")
class NetworkNotFound(NotFound): message = _("Network \"%(network_name)s\" could not be found.")
class InvalidParameterValue(Invalid): message = _("%(err)s")
class StorageBackendNotFound(NotFound): message = _( 'Storage backend with name "%(storage_name)s" could not be found.')
class InvalidAuthKey(Invalid): message = _("Invalid auth key: %(reason)s")
class FlavorNotFound(NotFound): message = _("Flavor \"%(flavor_name)s\" could not be found.")
class InvalidConfigurationValue(Invalid): message = _('Value "%(value)s" is not valid for ' 'configuration option "%(option)s"')
class VolumeNotFound(NotFound): message = _("Volume \"%(volume_id)s\" could not be found.")
class InvalidTaskState(Invalid): message = _('Task "%(task_id)s" in in an invalid state: %(task_state)s')
class VolumeBackupNotFound(NotFound): message = _("Volume backup \"%(backup_id)s\" could not be found.")
class TaskIsCancelling(InvalidTaskState): message = _(TASK_ALREADY_CANCELLING_EXCEPTION_FMT)
class ConfigNotFound(NotFound): message = _("Could not find config at %(path)s")
class InvalidTaskResult(InvalidTaskState): message = _('Task returned an invalid result.')