Exemplo n.º 1
0
    def __call__(self, environ, start_response):
        #pass through if no exceptions occur
        try:
            return self.application(environ, start_response)
        # handle HTTP errors
        except exc.HTTPException as err:
            log.debug(u"{0} Thrown: {1}".format(err.__class__.__name__, err))
            # if the middleware is configured with an error controller
            # use that to display the errors
            if self.error_controller:
                handler = self.error_controller(err, status_code=err.code)

                try:
                    # try executing error_handler code
                    # otherwise re-raise the exception
                    return handler(environ, start_response)
                except Exception:
                    log.exception("Exception thrown during error_controller handling")
                    raise
            else:
                # HTTPExceptions are also WSGI apps and can be called as such
                return err(environ, start_response)
        except Exception as err:
            log.exception("General Exception thrown")
            if self.error_controller:
                handler = self.error_controller(err, message=str(err))
            else:
                # create a generic HTTP server Error webob exception
                handler = exc.HTTPServerError('General Fault')
            return handler(environ, start_response)
Exemplo n.º 2
0
    def delete(self, req, id):
        """Delete a plan."""
        context = req.environ['karbor.context']

        LOG.info("Delete plan with id: %s", id, context=context)

        try:
            plan = self._plan_get(context, id)
        except exception.PlanNotFound as error:
            raise exc.HTTPNotFound(explanation=error.msg)

        context.can(plan_policy.DELETE_POLICY, target_obj=plan)
        project_id = plan.project_id

        try:
            plan.destroy()
        except Exception:
            msg = _("Failed to destroy a plan.")
            raise exc.HTTPServerError(reason=msg)

        try:
            reserve_opts = {'plans': -1}
            reservations = QUOTAS.reserve(context,
                                          project_id=project_id,
                                          **reserve_opts)
        except Exception:
            LOG.exception("Failed to update usages deleting plan.")
        else:
            QUOTAS.commit(context, reservations, project_id=project_id)
        LOG.info("Delete plan request issued successfully.",
                 resource={'id': plan.id})
Exemplo n.º 3
0
    def get_by_name(self, req):
        """ Get one vsm setting by name
        """
        context = req.environ['vsm.context']
        search_opts = {}
        search_opts.update(req.GET)

        LOG.debug('search options %s' % search_opts)
        vsm_name = search_opts.pop('name', None)
        if not vsm_name:
            raise exc.HTTPBadRequest(
                explanation=_('Invalid request: vsm name is required.'))

        try:
            utils.check_string_length(vsm_name,
                                      'name',
                                      min_length=1,
                                      max_length=255)
            setting = db.vsm_settings_get_by_name(context, vsm_name)
        except db_exc.DBError as e:
            raise exc.HTTPServerError(explanation=e.message)
        except exception.InvalidInput as e:
            raise exc.HTTPBadRequest(explanation=e.message)

        if not setting:
            raise exc.HTTPNotFound(
                explanation=_('The vsm setting(%s) does not exists.' %
                              vsm_name))

        return self._view_builder.basic(req, setting)
Exemplo n.º 4
0
    def _detach_nbs_volume(self, req, server_id, id):
        """Detach a nbs volume from an instance."""
        if FLAGS.nbs_api_server is None:
            explanation = _("Cannot detach nbs volume, nbs server is None.")
            raise exc.HTTPServerError(explanation=explanation)
        context = req.environ['nova.context']
        authorize(context)

        volume_id = id
        LOG.audit(_("Detach nbs volume %(volume)s from instance %(server)s")
                % {"volume": volume_id, "server": server_id}, context=context)

        try:
            instance = self.compute_api.get(context, server_id)
        except exception.NotFound:
            explanation = _("Instance %s not found.") % server_id
            raise exc.HTTPNotFound(explanation=explanation)

        try:
            self.compute_api.detach_nbs_volume(context,
                    instance, volume_id)
        except exception.VolumeNotFound:
            explanation = _("Volume not found.")
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.Invalid:
            explanation = _("Volume is not attached.")
            raise exc.HTTPNotFound(explanation=explanation)
        else:
            return {'requestId': context.request_id, 'return': True}
Exemplo n.º 5
0
    def __call__(self, req):
        """Handles the HTTP POST request.

        Attempts to interpret all HTTP POST requests as XML-RPC calls,
        which are forwarded to the server's _dispatch method for
        handling.

        Most code taken from SimpleXMLRPCServer with modifications for
        wsgi and my custom dispatcher.
        """
        if req.method != 'POST':
            return exc.HTTPBadRequest()
        try:
            data = req.environ['wsgi.input'].read(req.content_length)
            response = self.dispatcher._marshaled_dispatch(
                data, self.dispatcher._dispatch) + b'\n'
        except:  # pragma: no cover
            # This should only happen if the module is buggy
            # internal error, report as HTTP server error
            return exc.HTTPServerError()
        else:
            # got a valid XML RPC response
            response = Response(response)
            response.content_type = 'text/xml'
            return response
Exemplo n.º 6
0
    def _create_setting(self, context, setting_dict):

        try:
            return db.vsm_settings_update_or_create(context, setting_dict)

        except db_exc.DBError as e:
            raise exc.HTTPServerError(explanation=e.message)
Exemplo n.º 7
0
 def update_phyname_of_network(self, req, body):
     try:
         self.db_api.update_phyname_of_network(req.context, body)
         return {}
     except exception.NotFound:
         raise exc.HTTPServerError(
             explanation="Update database for phyname of network "
             "table failed!")
Exemplo n.º 8
0
    def get_all_networks(self, req):
        params = self._get_query_params(req)
        try:
            networks = self.db_api.network_get_all(req.context, **params)
        except Exception:
            raise exc.HTTPServerError(explanation="Get all networks failed")

        return networks
Exemplo n.º 9
0
    def _create_setting(self, context, setting_dict):

        try:
            if setting_dict.get('name') in ['cpu_diamond_collect_interval','ceph_diamond_collect_interval']:
                 self.scheduler_api.reconfig_diamond(context, setting_dict)
            return db.vsm_settings_update_or_create(context, setting_dict)

        except db_exc.DBError as e:
            raise exc.HTTPServerError(explanation=e.message)
Exemplo n.º 10
0
 def view(self, req):
     """
     View old exception reports
     """
     id = int(req.path_info_pop())
     if id not in self.debug_infos:
         return exc.HTTPServerError(
             "Traceback by id %s does not exist (maybe "
             "the server has been restarted?)" % id)
     debug_info = self.debug_infos[id]
     return debug_info.wsgi_application
Exemplo n.º 11
0
    def _generate_get_error(self):
        """Falcon exception generator to throw from early-exit mocks.

        Creates an exception that should be raised by GET tests that pass
        RBAC. This allows such flows to short-circuit normal post-RBAC
        processing that is not tested in this module.
        :return: Python exception that should be raised by repo get methods.
        """
        # The 'Read Error' clause needs to match that asserted in
        #    _assert_post_rbac_exception() above.
        return exc.HTTPServerError(detail='Read Error')
Exemplo n.º 12
0
    def upload(self, req, body=None):
        """Upload new file archive for the new package
           together with package metadata.
        """
        policy.check("upload_package", req.context)

        _check_content_type(req, 'multipart/form-data')
        file_obj, package_meta = _validate_body(body)
        if package_meta:
            try:
                jsonschema.validate(package_meta, schemas.PKG_UPLOAD_SCHEMA)
            except jsonschema.ValidationError as e:
                LOG.exception(e)
                raise exc.HTTPBadRequest(explanation=e.message)
        else:
            package_meta = {}

        with tempfile.NamedTemporaryFile(delete=False) as tempf:
            LOG.debug("Storing package archive in a temporary file")
            content = file_obj.file.read()
            if not content:
                msg = _("Uploading file can't be empty")
                LOG.error(msg)
                raise exc.HTTPBadRequest(msg)
            tempf.write(content)
            package_meta['archive'] = content
        try:
            pkg_to_upload = load_utils.load_from_file(tempf.name,
                                                      target_dir=None,
                                                      drop_dir=True)
        except pkg_exc.PackageLoadError as e:
            LOG.exception(e)
            raise exc.HTTPBadRequest(e)
        finally:
            LOG.debug("Deleting package archive temporary file")
            os.remove(tempf.name)

        # extend dictionary for update db
        for k, v in PKG_PARAMS_MAP.iteritems():
            if hasattr(pkg_to_upload, k):
                package_meta[v] = getattr(pkg_to_upload, k)

        if req.params.get('is_public', '').lower() == 'true':
            policy.check('publicize_image', req.context)
            package_meta['is_public'] = True

        try:
            package = db_api.package_upload(package_meta, req.context.tenant)
        except db_exc.DBDuplicateEntry:
            msg = _('Package with specified full name is already registered')
            LOG.exception(msg)
            raise exc.HTTPServerError(msg)
        return package.to_dict()
Exemplo n.º 13
0
 def __call__(self, req):
     '''
     The ErrorController will return a formatted stack trace if in debug
     mode, or point to a regular error page otherwise.
     '''
     if 400 <= int(self.status_code) < 500:
         return req.get_response(self.exception)
     else:
         if config.debug:
             stack_trace = render(template='stack_trace', data={'req': req})
             return Response(body=stack_trace, status=self.status_code)
         else:
             return req.get_response(exc.HTTPServerError('General Fault'))
Exemplo n.º 14
0
 def ogcserver_app(environ, start_response):
     from webob import Request
     req = Request(environ)
     try:
         resp = req.get_response(app)
         return resp(environ, start_response)
     except Exception, e:
         if not debug:
             log.error('%r: %s', e, e)
             log.error('%r', environ)
             from webob import exc
             return exc.HTTPServerError(str(e))(environ, start_response)
         else:
             raise
Exemplo n.º 15
0
    def _respond(cls, request):
        try:
            path_response = cls.__routes.match(request.path_info)
            if path_response[0] is None:
                raise exc.HTTPNotFound()

            endpoint = path_response[0]
            session = SessionObject(
                request.environ, **cls.__get_session_config())

            try:
                method = endpoint(request.method)
                result = method(
                    _Request(
                        session=session,
                        route_params=path_response[1],
                        path_for=cls.__routes.path_for,
                        raw=request
                    )
                )

            except Exception as e:
                raise exc.HTTPServerError()

            response = webob.Response()

            if session.accessed():
                if not session.dirty():
                    session.save()
                session.persist()
                cookie = session.__dict__['_headers']['cookie_out'] if \
                    session.__dict__['_headers']['set_cookie'] else None
                if cookie:
                    response.headers.add('Set-Cookie', cookie)

            if cls.__config['show_x_powered_by']:
                response.headers.add(
                    'X-Powered-By', 'Lulu version %s' % _VERSION)

            if isinstance(result, basestring):
                response.text = result
                response.charset = 'utf8'
            elif type(result) is dict:
                response.content_type = result['content_type'] if \
                    'content_type' in result.keys() else 'text/html'
                response.body = result['body']

            return response
        except exc.HTTPError as e:
            return e
Exemplo n.º 16
0
 def __call__(self, environ, start_response):
     req = Request(environ)
     action = req.path.strip('/').replace('/', '_') + '_' + req.method
     try:
         if hasattr(self, action):
             resp = Response(getattr(self, action)(req))
         else:
             resp = Response(exc.HTTPBadRequest('Incorrect path or method'))
     except exc.HTTPException as e:
         resp = e
     except ValueError:
         resp = exc.HTTPBadRequest('Incorrect data for request')
     except Exception as e:
         resp = exc.HTTPServerError(e.message)
     return resp(environ, start_response)
Exemplo n.º 17
0
    def _deleteFixedIPs(self, req, id, body):
        context = req.environ['nova.context']
        authorize(context, action='deleteFixedIPs')
        self._check_body(body, 'deleteFixedIPs')

        try:
            net = objects.Network.get_by_uuid(context, id)
            net.delete_fixed_ips(context)
        except exception.NotFound:
            msg = _('Network {net} not found'.format(net=id))
            LOG.error(msg)
            raise exc.HTTPNotFound()
        except exception.FixedIpAlreadyInUse as e:
            msg = _('Cannot delete, fixed ip in use: {e}'.format(e=e))
            LOG.error(msg)
            raise exc.HTTPServerError(detail=msg)

        return Response(status_int=202)
Exemplo n.º 18
0
    def show(self, req, id):
        context = req.environ['nova.context']
        authorize(context)
        LOG.debug(_("Listing server status"),
                  context=context,
                  instance_uuid=id)

        try:
            instance = self.compute_api.get(context, id)
            result = self.compute_api.instance_os_boot_ready(
                context, instance['uuid'], FLAGS.server_heartbeat_period)
            return result
        except exception.MemCacheClientNotFound:
            explanation = _("Memory cache client is not found.")
            raise exc.HTTPServerError(explanation=explanation)
        except exception.NotFound:
            explanation = _("Instance %s not found.") % id
            raise exc.HTTPNotFound(explanation=explanation)
Exemplo n.º 19
0
 def render(self, request, map):
     if request.method == 'POST':
         raw_data = request.body
     elif 'q' in request.GET:
         raw_data = request.GET['q']
     else:
         raise exc.HTTPBadRequest("No 'q' parameter specified").exception 
     
     try:
         d = json.loads(raw_data.decode('utf-8'))
     except:
         raise exc.HTTPBadRequest('Error parsing JSON').exception
     
     try:
         image, content_type, elapsed = self.nikweb_http.render(map, d)
     except:
         raise exc.HTTPServerError('Error rendering').exception
     
     resp = Response(body=image, content_type=content_type)
     resp.headers['X-nikweb-rendertime'] = "%0.3f" % elapsed
     return resp
Exemplo n.º 20
0
def get_debug_info(func):
    """
    A decorator (meant to be used under ``wsgiapp()``) that resolves
    the ``debugcount`` variable to a ``DebugInfo`` object (or gives an
    error if it can't be found).
    """
    def debug_info_replacement(self, req):
        if 'debugcount' not in req.params:
            return exc.HTTPBadRequest(
                "You must provide a debugcount parameter")
        debugcount = req.params['debugcount']
        try:
            debugcount = int(debugcount)
        except ValueError, e:
            return exc.HTTPBadRequest("Invalid value for debugcount (%r): %s" %
                                      (debugcount, e))
        if debugcount not in self.debug_infos:
            return exc.HTTPServerError(
                "Debug %s not found (maybe it has expired, or the server was restarted)"
                % debugcount)
        req.debug_info = self.debug_infos[debugcount]
        return func(self, req)
Exemplo n.º 21
0
 def __call__(self, request):
     client_name = request.environ.get('REMOTE_USER')
     if not client_name:
         raise u2f_error(BadInputException('Client not specified'))
     try:
         resp = self.client(request, client_name)
         if not isinstance(resp, Response):
             resp = Response(json.dumps(resp),
                             content_type='application/json')
         return resp
     except Exception as e:
         self._session.rollback()
         if isinstance(e, U2fException):
             e = u2f_error(e)
         elif isinstance(e, exc.HTTPException):
             pass
         else:
             log.exception('Server error')
             e = exc.HTTPServerError(e.args[0])
         raise e
     finally:
         self._session.commit()
Exemplo n.º 22
0
    def _attach_nbs_volume(self, req, server_id, body):
        """Attach a nbs volume to an instance."""
        if FLAGS.nbs_api_server is None:
            explanation = _("Cannot attach nbs volume, nbs server is None.")
            raise exc.HTTPServerError(explanation=explanation)
        context = req.environ['nova.context']
        authorize(context)

        if not self.is_valid_body(body, 'volumeAttachment'):
            explanation = _("Invalid paramater in body.")
            raise exc.HTTPUnprocessableEntity(explanation=explanation)

        volume_id = body['volumeAttachment'].get('volumeId')
        if not volume_id:
            explanation = _("Invalid paramater in body.")
            raise exc.HTTPUnprocessableEntity(explanation=explanation)

        LOG.audit(_("Attach nbs volume %(volume)s to instance %(server)s")
                % {"volume": volume_id, "server": server_id}, context=context)

        try:
            instance = self.compute_api.get(context, server_id)
            # Check os status if instance is 'ACTIVE'
            if instance['vm_state'] == vm_states.ACTIVE:
                os_status = self.compute_api.instance_os_boot_ready(context,
                                                instance['uuid'],
                                                FLAGS.server_heartbeat_period)
                if os_status['status'] != "up":
                    explanation = _("Cannot attach volume while instance os "
                                    "is starting.")
                    raise exc.HTTPForbidden(explanation=explanation)
            device = self.compute_api.attach_nbs_volume(context, instance,
                                                        volume_id)
        except exception.MemCacheClientNotFound:
            explanation = _("Memory cache client is not found.")
            raise exc.HTTPServerError(explanation=explanation)
        except exception.VolumeNotFound:
            explanation = _("Volume not found.")
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.NotFound:
            explanation = _("Instance %s not found.") % server_id
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.NoFreeDevice:
            explanation = _("No free device to attach volume.")
            raise exc.HTTPUnprocessableEntity(explanation=explanation)
        except exception.Invalid:
            explanation = _("Volume is not available.")
            raise exc.HTTPForbidden(explanation=explanation)
        except exception.NbsAttachForbidden:
            explanation = _("Instance %s is forbidden to attach "
                            "volume.") % server_id
            raise exc.HTTPForbidden(explanation=explanation)

        # The attach is async
        attachment = {}
        attachment['instanceId'] = instance['uuid']
        attachment['volumeId'] = volume_id
        attachment['device'] = device
        attachment['status'] = "attaching"
        attachment['attachTime'] = long(time.time())

        # NOTE(justinsb): And now, we have a problem...
        # The attach is async, so there's a window in which we don't see
        # the attachment (until the attachment completes).  We could also
        # get problems with concurrent requests.  I think we need an
        # attachment state, and to write to the DB here, but that's a bigger
        # change.
        # For now, we'll probably have to rely on libraries being smart

        # TODO(justinsb): How do I return "accepted" here?
        return {'attachment': attachment, 'requestId': context.request_id}
Exemplo n.º 23
0
    def __call__(self, environ, start_response):

        req = Request(environ)
        step = req.path_info.strip('/')

        try:

            if step in [i[0] for i in self.steps]:
                # determine which step we are on
                index = [i[0] for i in self.steps].index(step)
            else:
                # delegate to Trac

                environ['trac.env_parent_dir'] = self.directory
                environ['trac.env_index_template'] = self.index

                # data for index template
                if req.remote_user and self.remote_user_name:
                    # XXX fails if unicode
                    req.remote_user = str(
                        self.remote_user_name(req.remote_user))
                data = {
                    'remote_user': req.remote_user or '',
                    'auth': self.auth and 'yes' or ''
                }
                environ['trac.template_vars'] = ','.join(
                    ["%s=%s" % (key, value) for key, value in data.items()])
                return dispatch_request(environ, start_response)

            # if self.auth, enforce remote_user to be set
            if self.auth and not req.remote_user:
                return exc.HTTPUnauthorized()(environ, start_response)

            # if POST-ing, validate the request and store needed information
            errors = []
            name, step = self.steps[index]
            base_url = req.url.rsplit(step.name, 1)[0]
            project = req.params.get('project')
            if req.method == 'POST':

                # check for project existence
                if not project and index:
                    res = exc.HTTPSeeOther("No session found",
                                           location="create-project")
                    return res(environ, start_response)
                if index:
                    if project not in self.projects:
                        errors.append('Project not found')

                project_data = self.projects.get(project)
                errors = step.errors(project_data, req.POST)
                if not index:
                    project_data = self.projects[project] = {}

                # set *after* error check so that `create-project` doesn't find itself
                project_data['base_url'] = base_url

                if not errors:  # success
                    step.transition(project_data, req.POST)

                    # find the next step and redirect to it
                    while True:
                        index += 1

                        if index == len(self.steps):
                            destination = self.done % self.projects[project][
                                'vars']
                            time.sleep(1)  # XXX needed?
                            self.projects.pop(
                                project)  # successful project creation
                            break
                        else:
                            name, step = self.steps[index]
                            if step.display(project_data):
                                destination = '%s?project=%s' % (
                                    self.steps[index][0], project)
                                break
                            else:
                                step.transition(project_data, {})
                    res = exc.HTTPSeeOther(destination, location=destination)
                    return res(environ, start_response)

            else:  # GET
                project_data = self.projects.get(project, {})
                project_data['base_url'] = base_url
                if index and project not in self.projects:
                    res = exc.HTTPSeeOther("No session found",
                                           location="create-project")
                    return res(environ, start_response)

            # render the template and return the response
            data = step.data(project_data)
            data['req'] = req
            data['errors'] = errors
            template = self.loader.load(step.template)
            html = template.generate(**data).render('html', doctype='html')
            res = Response(content_type='text/html', body=html)
            return res(environ, start_response)

        except:
            # error handling
            exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
            buffer = StringIO()
            traceback.print_exception(exceptionType,
                                      exceptionValue,
                                      exceptionTraceback,
                                      limit=20,
                                      file=buffer)
            res = exc.HTTPServerError(buffer.getvalue())
            return res(environ, start_response)
Exemplo n.º 24
0
 def _wsgi_remove_object_exc(self, environ, start_response):
     p = self.Parent.query.get()
     p.delete()
     err = exc.HTTPServerError('Test Error')
     assert False
Exemplo n.º 25
0
    def _extend_nbs_volume(self, req, id, body):
        """Extend a exists nbs volume."""
        if FLAGS.nbs_api_server is None:
            explanation = _("Cannot extend nbs volume, nbs server is None.")
            raise exc.HTTPServerError(explanation=explanation)
        context = req.environ['nova.context']
        authorize(context)

        if 'size' not in body or not isinstance(body['size'], int):
            explanation = _("Invalid paramater in body.")
            raise exc.HTTPUnprocessableEntity(explanation=explanation)

        LOG.audit(_("Extend nbs volume %s") % id, context=context)

        size = body['size']    # in GB
        try:
            can_extend = self.compute_api.check_nbs_size(context, id, size)
            if not can_extend:
                explanation = _("Cannot extend volume, invalid size is given.")
                raise exc.HTTPForbidden(explanation=explanation)
        except exception.VolumeNotFound:
            explanation = _("Volume not found.")
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.NbsException:
            explanation = _("Nbs volume server error.")
            raise exc.HTTPServerError(explanation=explanation)

        try:
            instance_uuid = self.compute_api.check_nbs_attached(context, id)
        except exception.NotFound:
            explanation = _("Volume not found.")
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.Invalid:
            LOG.info(_("Volume %s is not attached.") % id)
            instance_uuid = None

        if instance_uuid is not None:
            try:
                # check instance exists
                instance = self.compute_api.get(context, instance_uuid)
                # Check os status if instance is 'ACTIVE'
                if instance['vm_state'] == vm_states.ACTIVE:
                    server_heartbeat_period = FLAGS.get(
                                                'server_heartbeat_period', 10)
                    os_status = self.compute_api.instance_os_boot_ready(
                                                    context,
                                                    instance['uuid'],
                                                    server_heartbeat_period)
                    if os_status['status'] != "up":
                        explanation = _("Cannot extend volume while instance "
                                        "os is starting.")
                        raise exc.HTTPForbidden(explanation=explanation)
            except exception.MemCacheClientNotFound:
                explanation = _("Memory cache client is not found.")
                raise exc.HTTPServerError(explanation=explanation)
            except exception.NotFound:
                explanation = _("Instance %s not found.") % instance_uuid
                raise exc.HTTPNotFound(explanation=explanation)

            # notify instance about this extension
            self.compute_api.extend_nbs_volume(context, id, size, instance)
        else:
            # call nbs to extend this volume directly
            self.compute_api.extend_nbs_volume(context, id, size)

        return {'requestId': context.request_id, 'size': size}
Exemplo n.º 26
0
    def _update_nbs_qos(self, req, server_id, id, body):
        """Update QoS parameters of nbs volume."""
        if FLAGS.nbs_api_server is None:
            explanation = _("Cannot update nbs qos info, nbs server is None.")
            raise exc.HTTPServerError(explanation=explanation)
        context = req.environ['nova.context']
        authorize(context)

        vol_project = None
        if context.is_admin:
            vol_project = req.headers.get('X-Vol-Project')
            if not vol_project:
                explanation = _("Project ID of volume is invalid.")
                raise exc.HTTPUnprocessableEntity(explanation=explanation)

        iotune_total_bytes = body.get('maxBandWidth')
        iotune_total_iops = body.get('maxIOPS')
        iotune_read_bytes = body.get('maxReadBandWidth')
        iotune_write_bytes = body.get('maxWriteBandWidth')
        iotune_read_iops = body.get('maxReadIOPS')
        iotune_write_iops = body.get('maxWriteIOPS')

        qos_info = {}
        if (iotune_read_bytes is not None or
                iotune_write_bytes is not None or
                iotune_read_iops is not None or
                iotune_write_iops is not None):
            if iotune_read_bytes is not None:
                qos_info['iotune_read_bytes'] = iotune_read_bytes
            if iotune_write_bytes is not None:
                qos_info['iotune_write_bytes'] = iotune_write_bytes
            if iotune_read_iops is not None:
                qos_info['iotune_read_iops'] = iotune_read_iops
            if iotune_write_iops is not None:
                qos_info['iotune_write_iops'] = iotune_write_iops
        elif (iotune_total_bytes is not None or
                iotune_total_iops is not None):
            if iotune_total_bytes is not None:
                qos_info['iotune_total_bytes'] = iotune_total_bytes
            if iotune_total_iops is not None:
                qos_info['iotune_total_iops'] = iotune_total_iops
        else:
            explanation = _("Invalid paramater in body.")
            raise exc.HTTPUnprocessableEntity(explanation=explanation)

        for value in qos_info.values():
            if not isinstance(value, int):
                explanation = _("Invalid paramater in body.")
                raise exc.HTTPUnprocessableEntity(explanation=explanation)

        volume_id = id
        LOG.audit(_("Update qos info of nbs volume %(volume)s on instance "
                    "%(server)s to %(qos_info)s") % {"volume": volume_id,
                                                     "server": server_id,
                                                     "qos_info": qos_info},
                    context=context)

        try:
            instance = self.compute_api.get(context, server_id)
        except exception.NotFound:
            explanation = _("Instance %s not found.") % server_id
            raise exc.HTTPNotFound(explanation=explanation)

        # FIXME(wangpan): this API is used by nbs admin user, so the context
        #                 is belong to nova admin user for updating qos info
        #                 of all instances, but while calling the nbs API,
        #                 the real project id of volume is needed, so change
        #                 it here manually.
        if context.is_admin and vol_project:
            context.project_id = vol_project

        try:
            self.compute_api.check_nbs_attached(context, volume_id,
                                                instance['uuid'])
        except exception.NotFound:
            explanation = _("Volume not found.")
            raise exc.HTTPNotFound(explanation=explanation)
        except exception.Invalid:
            explanation = _("Volume is not attached.")
            raise exc.HTTPNotFound(explanation=explanation)
        else:
            self.compute_api.update_nbs_qos(context, instance, volume_id,
                                            qos_info)

        return {'requestId': context.request_id, 'return': True}