diff --git a/neutron/api/v2/base.py b/neutron/api/v2/base.py index 30c4c1c56db..84f9cb05ed7 100644 --- a/neutron/api/v2/base.py +++ b/neutron/api/v2/base.py @@ -593,7 +593,8 @@ class Controller(object): @db_api.retry_db_errors def _update(self, request, id, body, **kwargs): - body = Controller.prepare_request_body(request.context, body, False, + body = Controller.prepare_request_body(request.context, + copy.deepcopy(body), False, self._resource, self._attr_info, allow_bulk=self._allow_bulk) action = self._plugin_handlers[self.UPDATE] diff --git a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py index 3413667aa46..a6423c4da90 100644 --- a/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py +++ b/neutron/tests/unit/extensions/test_l3_ext_gw_mode.py @@ -17,6 +17,7 @@ import mock from neutron_lib import constants from oslo_config import cfg +from oslo_db import exception as db_exc from oslo_serialization import jsonutils from oslo_utils import uuidutils import testscenarios @@ -389,6 +390,19 @@ class ExtGwModeIntTestCase(test_db_base_plugin_v2.NeutronDbPluginV2TestCase, expected_code=expected_code, neutron_context=neutron_context) + def test_router_gateway_set_retry(self): + with self.router() as r, self.subnet() as s: + ext_net_id = s['subnet']['network_id'] + self._set_net_external(ext_net_id) + with mock.patch.object( + l3_db.L3_NAT_dbonly_mixin, '_validate_gw_info', + side_effect=[db_exc.RetryRequest(None), ext_net_id]): + self._set_router_external_gateway(r['router']['id'], + ext_net_id) + res = self._show('routers', r['router']['id'])['router'] + self.assertEqual(ext_net_id, + res['external_gateway_info']['network_id']) + def test_router_create_with_gwinfo_invalid_ext_ip(self): with self.subnet() as s: self._set_net_external(s['subnet']['network_id'])