From 2a27361cf50259281924dbdaba3f06367ef327e7 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Wed, 3 Feb 2016 23:17:06 -0800 Subject: [PATCH] Protect 'show' and 'index' with Retry decorator Commit 77de9653fd60a802b11f157972f7b3e81497e8a7 added a RetryRequest exception to the policy engine for when items disappeared during policy enforcement lookups. However, the API was not catching them for the show and list operations. This patch adds the decorators to the two methods to catch any retry exception that may be emitted from the policy engine or wherever else. Closes-Bug: #1528031 Change-Id: If4aea5245cdbb2ea545e9a96d73386e3c21a3696 --- neutron/api/v2/base.py | 2 ++ neutron/tests/unit/api/v2/test_base.py | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/neutron/api/v2/base.py b/neutron/api/v2/base.py index 80a51dbc86c..18fbe3710b3 100644 --- a/neutron/api/v2/base.py +++ b/neutron/api/v2/base.py @@ -332,6 +332,7 @@ class Controller(object): if hasattr(self, '_nova_notifier'): self._nova_notifier.send_network_change(action, orig, returned) + @db_api.retry_db_errors def index(self, request, **kwargs): """Returns a list of the requested entity.""" parent_id = kwargs.get(self._parent_id_name) @@ -339,6 +340,7 @@ class Controller(object): policy.init() return self._items(request, True, parent_id) + @db_api.retry_db_errors def show(self, request, id, **kwargs): """Returns detailed information about the requested entity.""" try: diff --git a/neutron/tests/unit/api/v2/test_base.py b/neutron/tests/unit/api/v2/test_base.py index 7e3dbc3f19a..5c84bb2a7ae 100644 --- a/neutron/tests/unit/api/v2/test_base.py +++ b/neutron/tests/unit/api/v2/test_base.py @@ -17,6 +17,7 @@ import os import mock from oslo_config import cfg +from oslo_db import exception as db_exc from oslo_policy import policy as oslo_policy from oslo_utils import uuidutils import six @@ -1113,6 +1114,20 @@ class JSONV2TestCase(APIv2TestBase, testlib_api.WebTestCase): expect_errors=True) self.assertEqual(res.status_int, 400) + def test_retry_on_index(self): + instance = self.plugin.return_value + instance.get_networks.side_effect = [db_exc.RetryRequest(None), []] + api = webtest.TestApp(router.APIRouter()) + api.get(_get_path('networks', fmt=self.fmt)) + self.assertTrue(instance.get_networks.called) + + def test_retry_on_show(self): + instance = self.plugin.return_value + instance.get_network.side_effect = [db_exc.RetryRequest(None), {}] + api = webtest.TestApp(router.APIRouter()) + api.get(_get_path('networks', _uuid(), fmt=self.fmt)) + self.assertTrue(instance.get_network.called) + class SubresourceTest(base.BaseTestCase): def setUp(self):