Change Resource.__call__() to not leak internal errors.

That method now catches any non-expected errors raised by the controller's
action method and turn them into an HTTPServerError. Fixes bug 980033.

Change-Id: I7f71c029fae0e27a799f11de0802bde1003683e2
This commit is contained in:
Guilherme Salgado 2012-05-02 08:36:56 -03:00
parent 88fab71350
commit d1c563c57d
7 changed files with 41 additions and 3 deletions

View File

@ -27,6 +27,15 @@ Running tests
After running all of the tests, run_test.sh will report any pep8 errors
found in the tree.
Running individual tests
Individual tests can be run using run_tests.py, you just need to pass
the dot-separated path to the module you want as an argument to it.
For example, the following would run only the APITestV11 tests from
quantum/tests/unit/test_api.py:
$ ./run_tests.sh quantum.tests.unit.test_api:APITestV11
Adding more tests
Quantum is a pretty new code base at this point and there is plenty of

View File

@ -55,7 +55,7 @@ def fault_body_function_v10(wrapped_exc):
def fault_body_function_v11(wrapped_exc):
""" This function creates the contents of the body for a fault
response for Quantum API v1.0.
response for Quantum API v1.1.
:param wrapped_exc: Exception thrown by the Quantum service
:type wrapped_exc: quantum.common.exceptions.QuantumException

View File

@ -18,8 +18,12 @@
# @author: Salvatore Orlando, Citrix Systems
import logging
import unittest
import unittest2 as unittest
import mock
from quantum.api.api_common import APIFaultWrapper
from quantum.api.networks import Controller
from quantum.common.test_lib import test_config
from quantum.common import utils
from quantum.db import api as db
@ -1187,3 +1191,21 @@ class BaseAPIOperationsTest(AbstractAPITest):
def test_multitenancy_json(self):
self._test_multitenancy('json')
def test_internal_error(self):
"""Check that internal errors do not leak.
Any internal, unexpected error should be turned into a 500 response
without any traces of the original exception.
"""
orig_exception_msg = "An exception with a traceback"
@APIFaultWrapper()
def raise_exception(self, *args, **kwargs):
raise Exception(orig_exception_msg)
list_network_req = testlib.network_list_request(self.tenant_id, "json")
with mock.patch.object(Controller, 'index', new=raise_exception):
list_network_res = list_network_req.get_response(self.api)
self.assertEqual(list_network_res.status_int, 500)
self.assertNotIn(orig_exception_msg, list_network_res.body)

View File

@ -752,6 +752,12 @@ class Resource(Application):
action_result = Fault(ex,
self._xmlns,
self._fault_body_function)
except Exception:
LOG.exception("Internal error")
# Do not include the traceback to avoid returning it to clients.
action_result = Fault(webob.exc.HTTPServerError(),
self._xmlns,
self._fault_body_function)
if isinstance(action_result, dict) or action_result is None:
response = self.serializer.serialize(action_result,

0
run_tests.py Normal file → Executable file
View File

View File

@ -3,7 +3,6 @@ PasteDeploy==1.5.0
Routes>=1.12.3
eventlet>=0.9.12
lxml
mox==0.5.3
python-gflags==1.3
sqlalchemy
webob==1.0.8

View File

@ -2,9 +2,11 @@ distribute>=0.6.24
coverage
mock>=0.7.1
mox==0.5.3
nose
nosexcover
openstack.nose_plugin
pep8==0.6.1
sphinx>=1.1.2
unittest2
webtest