DVR: on new port only send router update on port's host
When new DVR serviceable port appears on new node we need to update node's l3 agent with all routers which have the port's subnets, including connected routers. We don't need to update all nodes hosting these routers. It costs us much as all l3 agents then go back to neutron server and request routers info for no good reason. This was one of the main issues with DVR at scale fixed in Mitaka. Change-Id: I99d01d7bf29f236eff0f80d1ae8659f64ac55d39 Related-Bug: #1830456
This commit is contained in:
parent
17caf723fa
commit
52529bc949
neutron
db
tests
@ -13,8 +13,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
|
||||
from neutron_lib.api.definitions import portbindings
|
||||
from neutron_lib.api import extensions
|
||||
from neutron_lib.callbacks import events
|
||||
@ -139,26 +137,18 @@ class L3_DVRsch_db_mixin(l3agent_sch_db.L3AgentSchedulerDbMixin):
|
||||
if agent.host == port_host:
|
||||
agent_port_host_match = True
|
||||
if not agent_port_host_match:
|
||||
hosts = set([port_host])
|
||||
connected_router_ids = set(router_ids)
|
||||
for router_id in router_ids:
|
||||
hosts |= set(self.get_hosts_to_notify(context, router_id))
|
||||
connected_router_ids.update(
|
||||
self._get_other_dvr_router_ids_connected_router(
|
||||
context, router_id))
|
||||
|
||||
host_routers = collections.defaultdict(set)
|
||||
for router_id in router_ids:
|
||||
# avoid calling get_ports in host loop
|
||||
subnet_ids = self.get_subnet_ids_on_router(
|
||||
context.elevated(), router_id)
|
||||
for host in hosts:
|
||||
LOG.debug('DVR: Handle new service port, host %(host)s, '
|
||||
'router ids %(router_id)s',
|
||||
{'host': host, 'router_id': router_id})
|
||||
if self._check_dvr_serviceable_ports_on_host(
|
||||
context.elevated(), host, subnet_ids):
|
||||
host_routers[host].add(router_id)
|
||||
|
||||
for host, router_ids in host_routers.items():
|
||||
self.l3_rpc_notifier.routers_updated_on_host(
|
||||
context, router_ids, host)
|
||||
LOG.debug('DVR: Handle new service port, host %(host)s, '
|
||||
'router ids %(router_ids)s',
|
||||
{'host': port_host,
|
||||
'router_ids': connected_router_ids})
|
||||
self.l3_rpc_notifier.routers_updated_on_host(
|
||||
context, connected_router_ids, port_host)
|
||||
|
||||
def get_dvr_snat_agent_list(self, context):
|
||||
agent_filters = {'agent_modes': [n_const.L3_AGENT_MODE_DVR_SNAT]}
|
||||
|
@ -782,7 +782,6 @@ class L3DvrTestCase(L3DvrTestCaseBase):
|
||||
expected_routers_updated_calls = [
|
||||
mock.call(self.context, mock.ANY, 'host0'),
|
||||
mock.call(self.context, mock.ANY, HOST1),
|
||||
mock.call(self.context, mock.ANY, HOST1),
|
||||
mock.call(self.context, mock.ANY, HOST2)]
|
||||
l3_notifier.routers_updated_on_host.assert_has_calls(
|
||||
expected_routers_updated_calls, any_order=True)
|
||||
@ -1104,7 +1103,7 @@ class L3DvrTestCase(L3DvrTestCaseBase):
|
||||
{'port': {
|
||||
'allowed_address_pairs': allowed_address_pairs}})
|
||||
self.assertEqual(
|
||||
3, l3_notifier.routers_updated_on_host.call_count)
|
||||
2, l3_notifier.routers_updated_on_host.call_count)
|
||||
updated_vm_port1 = self.core_plugin.get_port(
|
||||
self.context, vm_port['id'])
|
||||
updated_vm_port2 = self.core_plugin.get_port(
|
||||
@ -1154,7 +1153,6 @@ class L3DvrTestCase(L3DvrTestCaseBase):
|
||||
expected_routers_updated_calls = [
|
||||
mock.call(self.context, mock.ANY, HOST1),
|
||||
mock.call(self.context, mock.ANY, HOST2),
|
||||
mock.call(self.context, mock.ANY, HOST1),
|
||||
mock.call(self.context, mock.ANY, 'host0')]
|
||||
l3_notifier.routers_updated_on_host.assert_has_calls(
|
||||
expected_routers_updated_calls, any_order=True)
|
||||
|
@ -1328,13 +1328,7 @@ class L3DvrSchedulerTestCase(L3SchedulerBaseMixin,
|
||||
'.L3AgentNotifyAPI'),\
|
||||
mock.patch.object(
|
||||
self.dut, 'get_l3_agents',
|
||||
return_value=[agent_on_host]) as get_l3_agents,\
|
||||
mock.patch.object(
|
||||
self.dut, 'get_hosts_to_notify',
|
||||
return_value=['other_host', 'host1']),\
|
||||
mock.patch.object(
|
||||
self.dut, '_check_dvr_serviceable_ports_on_host',
|
||||
return_value=True):
|
||||
return_value=[agent_on_host]) as get_l3_agents:
|
||||
|
||||
self.dut.dvr_handle_new_service_port(
|
||||
self.adminContext, port)
|
||||
@ -1342,10 +1336,9 @@ class L3DvrSchedulerTestCase(L3SchedulerBaseMixin,
|
||||
get_l3_agents.assert_called_once_with(
|
||||
self.adminContext,
|
||||
filters={'host': [port[portbindings.HOST_ID]]})
|
||||
self.dut.l3_rpc_notifier.routers_updated_on_host.assert_has_calls(
|
||||
[mock.call(self.adminContext, {'r1', 'r2'}, 'host1'),
|
||||
mock.call(self.adminContext, {'r1', 'r2'}, 'other_host')],
|
||||
any_order=True)
|
||||
self.dut.l3_rpc_notifier.routers_updated_on_host.\
|
||||
assert_called_once_with(self.adminContext,
|
||||
{'r1', 'r2'}, 'host1')
|
||||
self.assertFalse(self.dut.l3_rpc_notifier.routers_updated.called)
|
||||
|
||||
def test_get_dvr_routers_by_subnet_ids(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user