]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
nec plugin: Avoid long transaction in delete_ports
authorAkihiro Motoki <motoki@da.jp.nec.com>
Fri, 21 Feb 2014 08:42:46 +0000 (17:42 +0900)
committerThomas Goirand <thomas@goirand.fr>
Thu, 13 Mar 2014 07:20:39 +0000 (15:20 +0800)
db_plugin.delete_ports() can lead to long transaction
if plugin.deleete_port talks with external system.
This commit removes a transaction in delete_ports and
allows NEC plugin to use more granular db transactions
in delete_port. It greatly helps db race conditions and
timeouts in delete_port operations.

To avoid to impact other plugins/drivers by changing
db_plugin.delete_ports directly and to land this patch soon,
this commit overrides delete_ports() in NEC plugin.
Further disssion on transaction in delete_ports will be
discussed under bug 1282925.

Closes-Bug: #1282922
Related-Bug: #1282925

Change-Id: I2c00694ad34eb2058bf7a0ff1c920ceded327d43

neutron/plugins/nec/nec_plugin.py
neutron/tests/unit/nec/test_nec_plugin.py

index fd69b20e70865a6f2d34f1feb2fd192d62d0e7f3..a4614bd60e1d1aa5f86c1b816c82ed9d4070989c 100644 (file)
@@ -31,6 +31,7 @@ from neutron.db import db_base_plugin_v2
 from neutron.db import dhcp_rpc_base
 from neutron.db import external_net_db
 from neutron.db import l3_rpc_base
+from neutron.db import models_v2
 from neutron.db import portbindings_base
 from neutron.db import portbindings_db
 from neutron.db import quota_db  # noqa
@@ -646,6 +647,18 @@ class NECPluginV2(db_base_plugin_v2.NeutronDbPluginV2,
             super(NECPluginV2, self).delete_port(context, id)
         self.notify_security_groups_member_updated(context, port)
 
+    def delete_ports(self, context, filters):
+        # Note(amotoki): Override the superclass method to avoid
+        # a long transaction over external API calls.
+        # TODO(amotoki): Need to revisit after bug 1282925 is addressed.
+        query = context.session.query(
+            models_v2.Port).enable_eagerloads(False)
+        query = self._apply_filters_to_query(
+            query, models_v2.Port, filters)
+        port_ids = [p['id'] for p in query]
+        for port_id in port_ids:
+            self.delete_port(context, port_id)
+
 
 class NECPluginV2AgentNotifierApi(proxy.RpcProxy,
                                   sg_rpc.SecurityGroupAgentRpcApiMixin):
index fa061cfad347385c3d052579e0dec5503d764af4..a0e27da394db3f5dbb3d6793e54c8002150a6b89 100644 (file)
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import contextlib
 import os
 
 import fixtures
@@ -127,7 +128,27 @@ class TestNecV2HTTPResponse(test_plugin.TestV2HTTPResponse,
 
 
 class TestNecPortsV2(test_plugin.TestPortsV2, NecPluginV2TestCase):
-    pass
+
+    def test_delete_ports(self):
+        with self.subnet() as subnet:
+            with contextlib.nested(
+                self.port(subnet=subnet, device_owner='test-owner',
+                          no_delete=True),
+                self.port(subnet=subnet, device_owner='test-owner',
+                          no_delete=True),
+                self.port(subnet=subnet, device_owner='other-owner'),
+            ) as (p1, p2, p3):
+                network_id = subnet['subnet']['network_id']
+                filters = {'network_id': [network_id],
+                           'device_owner': ['test-owner']}
+                self.plugin.delete_ports(self.context, filters)
+
+                self._show('ports', p1['port']['id'],
+                           expected_code=webob.exc.HTTPNotFound.code)
+                self._show('ports', p2['port']['id'],
+                           expected_code=webob.exc.HTTPNotFound.code)
+                self._show('ports', p3['port']['id'],
+                           expected_code=webob.exc.HTTPOk.code)
 
 
 class TestNecNetworksV2(test_plugin.TestNetworksV2, NecPluginV2TestCase):