From 2f0c352973ebd7d062f4d1818adb8e05093169f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Weing=C3=A4rtner?= Date: Thu, 13 Aug 2020 09:42:34 -0300 Subject: [PATCH] Log exception generated in Controller.prepare_request_body While implementing some Neutron extension, I noticed that whenever a parameter that is expected by the API is not entered, we receive an internal error message. However, from the user/operator/dev calling the API, it might not be clear what the error is. Therefore, we should at least, log these validation errors. This patch proposes to enclose the call to Controller.prepare_request_body with a try/except block, and then we log the exception in warning level. After logging the exception, we raise it to allow the normal execution flow to continue. Change-Id: I855442ee8c0c4b4f0aff19968a5db07fca898146 --- neutron/api/v2/base.py | 47 ++++++++++++++------- neutron/extensions/quotasv2.py | 14 ++++-- neutron/pecan_wsgi/hooks/body_validation.py | 24 ++++++++--- 3 files changed, 60 insertions(+), 25 deletions(-) diff --git a/neutron/api/v2/base.py b/neutron/api/v2/base.py index bec1a62197d..7c4793463d3 100644 --- a/neutron/api/v2/base.py +++ b/neutron/api/v2/base.py @@ -440,10 +440,15 @@ class Controller(object): def _create(self, request, body, **kwargs): """Creates a new instance of the requested entity.""" parent_id = kwargs.get(self._parent_id_name) - body = Controller.prepare_request_body(request.context, - body, True, - self._resource, self._attr_info, - allow_bulk=self._allow_bulk) + try: + body = Controller.prepare_request_body( + request.context, body, True, self._resource, self._attr_info, + allow_bulk=self._allow_bulk) + except Exception as e: + LOG.warning("An exception happened while processing the request " + "body. The exception message is [%s].", e) + raise e + action = self._plugin_handlers[self.CREATE] # Check authz if self._collection in body: @@ -626,10 +631,15 @@ class Controller(object): @db_api.retry_db_errors def _update(self, request, id, body, **kwargs): - body = Controller.prepare_request_body(request.context, - body, False, - self._resource, self._attr_info, - allow_bulk=self._allow_bulk) + try: + body = Controller.prepare_request_body( + request.context, body, False, self._resource, self._attr_info, + allow_bulk=self._allow_bulk) + except Exception as e: + LOG.warning("An exception happened while processing the request " + "body. The exception message is [%s].", e) + raise e + action = self._plugin_handlers[self.UPDATE] # Load object to check authz # but pass only attributes in the original body and required @@ -724,13 +734,20 @@ class Controller(object): "not supported")) if not body[collection]: raise webob.exc.HTTPBadRequest(_("Resources required")) - bulk_body = [ - Controller.prepare_request_body( - context, item if resource in item - else {resource: item}, is_create, resource, attr_info, - allow_bulk) for item in body[collection] - ] - return {collection: bulk_body} + try: + bulk_body = [ + Controller.prepare_request_body( + context, item if resource in item + else {resource: item}, is_create, resource, + attr_info, allow_bulk) for item in body[collection] + ] + return {collection: bulk_body} + except Exception as e: + LOG.warning( + "An exception happened while processing the request " + "body. The exception message is [%s].", e) + raise e + res_dict = body.get(resource) except (AttributeError, TypeError): msg = _("Body contains invalid data") diff --git a/neutron/extensions/quotasv2.py b/neutron/extensions/quotasv2.py index 4b2fb96a502..8de99519382 100644 --- a/neutron/extensions/quotasv2.py +++ b/neutron/extensions/quotasv2.py @@ -20,6 +20,7 @@ from neutron_lib.db import constants as const from neutron_lib import exceptions from neutron_lib.plugins import directory from oslo_config import cfg +from oslo_log import log as logging from oslo_utils import importutils import webob @@ -41,6 +42,7 @@ DB_QUOTA_DRIVER = 'neutron.db.quota.driver.DbQuotaDriver' EXTENDED_ATTRIBUTES_2_0 = { RESOURCE_COLLECTION: {} } +LOG = logging.getLogger(__name__) def validate_policy(context, policy_name): @@ -118,9 +120,15 @@ class QuotaSetsController(wsgi.Controller): validate_policy(request.context, "update_quota") if self._update_extended_attributes: self._update_attributes() - body = base.Controller.prepare_request_body( - request.context, body, False, self._resource_name, - EXTENDED_ATTRIBUTES_2_0[RESOURCE_COLLECTION]) + try: + body = base.Controller.prepare_request_body( + request.context, body, False, self._resource_name, + EXTENDED_ATTRIBUTES_2_0[RESOURCE_COLLECTION]) + except Exception as e: + LOG.warning( + "An exception happened while processing the request " + "body. The exception message is [%s].", e) + raise e for key, value in body[self._resource_name].items(): self._driver.update_quota_limit(request.context, id, key, value) return {self._resource_name: self._get_quotas(request, id)} diff --git a/neutron/pecan_wsgi/hooks/body_validation.py b/neutron/pecan_wsgi/hooks/body_validation.py index 50ac6a67fd7..38a4eccc611 100644 --- a/neutron/pecan_wsgi/hooks/body_validation.py +++ b/neutron/pecan_wsgi/hooks/body_validation.py @@ -13,7 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. +from oslo_log import log as logging from oslo_serialization import jsonutils + from pecan import hooks import webob.exc @@ -21,6 +23,8 @@ from neutron._i18n import _ from neutron.api.v2 import base as v2_base from neutron.pecan_wsgi.hooks import utils +LOG = logging.getLogger(__name__) + class BodyValidationHook(hooks.PecanHook): @@ -53,13 +57,19 @@ class BodyValidationHook(hooks.PecanHook): return # Prepare data to be passed to the plugin from request body controller = utils.get_controller(state) - data = v2_base.Controller.prepare_request_body( - neutron_context, - json_data, - is_create, - resource, - controller.resource_info, - allow_bulk=is_create) + try: + data = v2_base.Controller.prepare_request_body( + neutron_context, + json_data, + is_create, + resource, + controller.resource_info, + allow_bulk=is_create) + except Exception as e: + LOG.warning("An exception happened while processing the request " + "body. The exception message is [%s].", e) + raise e + if collection in data: state.request.context['resources'] = [item[resource] for item in data[collection]]