From e61865807c4c8ff959a7746fe3e17f1ae574c9d0 Mon Sep 17 00:00:00 2001 From: Kevin Benton Date: Wed, 3 Jun 2015 19:03:29 -0700 Subject: [PATCH] Defer segment lookup in NetworkContext object Avoid call to get network segments for network context objects until a caller actually tries to lookup the segments. This optimizes cases where the user of a port context never looks at the segments of the associated network context (e.g. update_port_status). Closes-Bug: #1463254 Change-Id: I7e95f81d9a3ef26ccdb18c6bfdf9adc29523aa79 --- neutron/plugins/ml2/driver_context.py | 7 +- .../unit/plugins/ml2/test_driver_context.py | 69 ++++++++++++------- 2 files changed, 51 insertions(+), 25 deletions(-) diff --git a/neutron/plugins/ml2/driver_context.py b/neutron/plugins/ml2/driver_context.py index ef418fe16e2..6e9b295b594 100644 --- a/neutron/plugins/ml2/driver_context.py +++ b/neutron/plugins/ml2/driver_context.py @@ -42,8 +42,8 @@ class NetworkContext(MechanismDriverContext, api.NetworkContext): super(NetworkContext, self).__init__(plugin, plugin_context) self._network = network self._original_network = original_network - self._segments = db.get_network_segments(plugin_context.session, - network['id']) + self._segments = None + self._session = plugin_context.session @property def current(self): @@ -55,6 +55,9 @@ class NetworkContext(MechanismDriverContext, api.NetworkContext): @property def network_segments(self): + if not self._segments: + self._segments = db.get_network_segments(self._session, + self._network['id']) return self._segments diff --git a/neutron/tests/unit/plugins/ml2/test_driver_context.py b/neutron/tests/unit/plugins/ml2/test_driver_context.py index e30349c9c6c..8171071b6c2 100644 --- a/neutron/tests/unit/plugins/ml2/test_driver_context.py +++ b/neutron/tests/unit/plugins/ml2/test_driver_context.py @@ -37,13 +37,12 @@ class TestPortContext(base.BaseTestCase): port = {'device_owner': constants.DEVICE_OWNER_DVR_INTERFACE} binding.host = 'foohost' - with mock.patch.object(driver_context.db, 'get_network_segments'): - ctx = driver_context.PortContext(plugin, - plugin_context, - port, - network, - binding, - None) + ctx = driver_context.PortContext(plugin, + plugin_context, + port, + network, + binding, + None) self.assertEqual('foohost', ctx.host) def test_host_super(self): @@ -56,13 +55,12 @@ class TestPortContext(base.BaseTestCase): portbindings.HOST_ID: 'host'} binding.host = 'foohost' - with mock.patch.object(driver_context.db, 'get_network_segments'): - ctx = driver_context.PortContext(plugin, - plugin_context, - port, - network, - binding, - None) + ctx = driver_context.PortContext(plugin, + plugin_context, + port, + network, + binding, + None) self.assertEqual('host', ctx.host) def test_status(self): @@ -74,13 +72,12 @@ class TestPortContext(base.BaseTestCase): port = {'device_owner': constants.DEVICE_OWNER_DVR_INTERFACE} binding.status = 'foostatus' - with mock.patch.object(driver_context.db, 'get_network_segments'): - ctx = driver_context.PortContext(plugin, - plugin_context, - port, - network, - binding, - None) + ctx = driver_context.PortContext(plugin, + plugin_context, + port, + network, + binding, + None) self.assertEqual('foostatus', ctx.status) def test_status_super(self): @@ -93,11 +90,37 @@ class TestPortContext(base.BaseTestCase): 'status': 'status'} binding.status = 'foostatus' - with mock.patch.object(driver_context.db, 'get_network_segments'): + ctx = driver_context.PortContext(plugin, + plugin_context, + port, + network, + binding, + None) + self.assertEqual('status', ctx.status) + + def test_segments_lazy_lookup(self): + plugin = mock.Mock() + plugin_context = mock.Mock() + network = mock.MagicMock() + binding = mock.Mock() + + port = {'device_owner': 'compute', + 'status': 'status'} + binding.status = 'foostatus' + + with mock.patch.object(driver_context.db, + 'get_network_segments') as gs: ctx = driver_context.PortContext(plugin, plugin_context, port, network, binding, None) - self.assertEqual('status', ctx.status) + self.assertFalse(gs.called) + # accessing the network_segments property should trigger + # a lookup the first time + seg = ctx.network.network_segments + self.assertTrue(gs.called) + gs.reset_mock() + self.assertEqual(seg, ctx.network.network_segments) + self.assertFalse(gs.called)