Merge "Reduce db calls count in get_devices_details_list"
This commit is contained in:
commit
ec716b9e68
@ -1182,7 +1182,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
self.notifier.port_delete(context, id)
|
||||
self.notify_security_groups_member_updated(context, port)
|
||||
|
||||
def get_bound_port_context(self, plugin_context, port_id, host=None):
|
||||
def get_bound_port_context(self, plugin_context, port_id, host=None,
|
||||
cached_networks=None):
|
||||
session = plugin_context.session
|
||||
with session.begin(subtransactions=True):
|
||||
try:
|
||||
@ -1199,7 +1200,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
||||
port_id)
|
||||
return
|
||||
port = self._make_port_dict(port_db)
|
||||
network = self.get_network(plugin_context, port['network_id'])
|
||||
network = (cached_networks or {}).get(port['network_id'])
|
||||
|
||||
if not network:
|
||||
network = self.get_network(plugin_context, port['network_id'])
|
||||
|
||||
if port['device_owner'] == const.DEVICE_OWNER_DVR_INTERFACE:
|
||||
binding = db.get_dvr_port_binding_by_host(
|
||||
session, port['id'], host)
|
||||
|
@ -58,6 +58,9 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
||||
agent_id = kwargs.get('agent_id')
|
||||
device = kwargs.get('device')
|
||||
host = kwargs.get('host')
|
||||
# cached networks used for reducing number of network db calls
|
||||
# for server internal usage only
|
||||
cached_networks = kwargs.get('cached_networks')
|
||||
LOG.debug("Device %(device)s details requested by agent "
|
||||
"%(agent_id)s with host %(host)s",
|
||||
{'device': device, 'agent_id': agent_id, 'host': host})
|
||||
@ -66,7 +69,8 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
||||
port_id = plugin._device_to_port_id(device)
|
||||
port_context = plugin.get_bound_port_context(rpc_context,
|
||||
port_id,
|
||||
host)
|
||||
host,
|
||||
cached_networks)
|
||||
if not port_context:
|
||||
LOG.warning(_LW("Device %(device)s requested by agent "
|
||||
"%(agent_id)s not found in database"),
|
||||
@ -75,6 +79,11 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
||||
|
||||
segment = port_context.bottom_bound_segment
|
||||
port = port_context.current
|
||||
# caching information about networks for future use
|
||||
if cached_networks is not None:
|
||||
if port['network_id'] not in cached_networks:
|
||||
cached_networks[port['network_id']] = (
|
||||
port_context.network.current)
|
||||
|
||||
if not segment:
|
||||
LOG.warning(_LW("Device %(device)s requested by agent "
|
||||
@ -109,10 +118,13 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
||||
return entry
|
||||
|
||||
def get_devices_details_list(self, rpc_context, **kwargs):
|
||||
# cached networks used for reducing number of network db calls
|
||||
cached_networks = {}
|
||||
return [
|
||||
self.get_device_details(
|
||||
rpc_context,
|
||||
device=device,
|
||||
cached_networks=cached_networks,
|
||||
**kwargs
|
||||
)
|
||||
for device in kwargs.pop('devices', [])
|
||||
|
@ -116,6 +116,26 @@ class PortBindingTestCase(test_plugin.NeutronDbPluginV2TestCase):
|
||||
portbindings.VIF_TYPE_OVS,
|
||||
False, True, network_type='vlan')
|
||||
|
||||
def test_get_bound_port_context_cache_hit(self):
|
||||
ctx = context.get_admin_context()
|
||||
with self.port(name='name') as port:
|
||||
cached_network_id = port['port']['network_id']
|
||||
some_network = {'id': cached_network_id}
|
||||
cached_networks = {cached_network_id: some_network}
|
||||
self.plugin.get_network = mock.Mock(return_value=some_network)
|
||||
self.plugin.get_bound_port_context(ctx, port['port']['id'],
|
||||
cached_networks=cached_networks)
|
||||
self.assertFalse(self.plugin.get_network.called)
|
||||
|
||||
def test_get_bound_port_context_cache_miss(self):
|
||||
ctx = context.get_admin_context()
|
||||
with self.port(name='name') as port:
|
||||
some_network = {'id': u'2ac23560-7638-44e2-9875-c1888b02af72'}
|
||||
self.plugin.get_network = mock.Mock(return_value=some_network)
|
||||
self.plugin.get_bound_port_context(ctx, port['port']['id'],
|
||||
cached_networks={})
|
||||
self.assertEqual(1, self.plugin.get_network.call_count)
|
||||
|
||||
def _test_update_port_binding(self, host, new_host=None):
|
||||
with mock.patch.object(self.plugin,
|
||||
'_notify_port_updated') as notify_mock:
|
||||
|
@ -103,6 +103,16 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
||||
self.assertEqual(status == new_status,
|
||||
not self.plugin.update_port_status.called)
|
||||
|
||||
def test_get_device_details_caching(self):
|
||||
port = collections.defaultdict(lambda: 'fake_port')
|
||||
cached_networks = {}
|
||||
self.plugin.get_bound_port_context().current = port
|
||||
self.plugin.get_bound_port_context().network.current = (
|
||||
{"id": "fake_network"})
|
||||
self.callbacks.get_device_details('fake_context', host='fake_host',
|
||||
cached_networks=cached_networks)
|
||||
self.assertTrue('fake_port' in cached_networks)
|
||||
|
||||
def test_get_devices_details_list(self):
|
||||
devices = [1, 2, 3, 4, 5]
|
||||
kwargs = {'host': 'fake_host', 'agent_id': 'fake_agent_id'}
|
||||
@ -113,7 +123,8 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
||||
**kwargs)
|
||||
self.assertEqual(devices, res)
|
||||
self.assertEqual(len(devices), f.call_count)
|
||||
calls = [mock.call('fake_context', device=i, **kwargs)
|
||||
calls = [mock.call('fake_context', device=i,
|
||||
cached_networks={}, **kwargs)
|
||||
for i in devices]
|
||||
f.assert_has_calls(calls)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user