Check gateway IP while looking for LR plugged to LS

When LB or member is created, driver looks for the Logical Router which
is plugged to the Logical Switch (Neutron network). As there can be more
than one router connected to one network, we should always store in
Loadbalancer's external_ids ID of the router which is used as default
gateway for the VIP's subnet.
This patch changes _find_lr_of_ls() method of the
ovn_octavia_provider.helper.OvnProviderHelper class so it checks
subnet's gateway IP while looks for the logical router.

Closes-bug: #1949059
Change-Id: I771f39ba190623857af208e23d8228c4bdc0db20
This commit is contained in:
Slawek Kaplonski 2021-11-05 18:48:34 +01:00
parent 1ee61f955f
commit ee800e1654
2 changed files with 37 additions and 10 deletions

View File

@ -623,10 +623,15 @@ class OvnProviderHelper():
'fetch its data.', sid)
return ls
def _find_lr_of_ls(self, ovn_ls):
def _find_lr_of_ls(self, ovn_ls, subnet_gateway_ip=None):
lsp_router_port = None
for port in ovn_ls.ports or []:
if port.type == 'router':
if subnet_gateway_ip:
port_cidr = netaddr.IPNetwork(
port.external_ids['neutron:cidrs']).ip
if netaddr.IPAddress(subnet_gateway_ip) != port_cidr:
continue
lsp_router_port = port
break
else:
@ -795,11 +800,17 @@ class OvnProviderHelper():
def lb_create(self, loadbalancer, protocol=None):
port = None
subnet = {}
neutron_client = clients.get_neutron_client()
if loadbalancer.get(constants.VIP_PORT_ID):
# In case we don't have vip_network_id
port = neutron_client.show_port(
loadbalancer[constants.VIP_PORT_ID])['port']
for ip in port['fixed_ips']:
if ip['ip_address'] == loadbalancer[constants.VIP_ADDRESS]:
subnet = neutron_client.show_subnet(
ip['subnet_id'])['subnet']
break
elif (loadbalancer.get(constants.VIP_NETWORK_ID) and
loadbalancer.get(constants.VIP_ADDRESS)):
ports = neutron_client.list_ports(
@ -808,6 +819,8 @@ class OvnProviderHelper():
for ip in p['fixed_ips']:
if ip['ip_address'] == loadbalancer[constants.VIP_ADDRESS]:
port = p
subnet = neutron_client.show_subnet(
ip['subnet_id'])['subnet']
break
# If protocol set make sure its lowercase
@ -849,7 +862,7 @@ class OvnProviderHelper():
ls_name = utils.ovn_name(port['network_id'])
ovn_ls = self.ovn_nbdb_api.ls_get(ls_name).execute(
check_error=True)
ovn_lr = self._find_lr_of_ls(ovn_ls)
ovn_lr = self._find_lr_of_ls(ovn_ls, subnet.get('gateway_ip'))
if ovn_lr:
commands.extend(self._update_lb_to_lr_association(
ovn_lb, ovn_lr))
@ -1503,7 +1516,8 @@ class OvnProviderHelper():
ls_name = utils.ovn_name(subnet['subnet']['network_id'])
ovn_ls = self.ovn_nbdb_api.ls_get(ls_name).execute(
check_error=True)
ovn_lr = self._find_lr_of_ls(ovn_ls)
ovn_lr = self._find_lr_of_ls(
ovn_ls, subnet['subnet'].get('gateway_ip'))
if ovn_lr:
for net in self._find_ls_for_lr(ovn_lr):
commands.append(self.ovn_nbdb_api.ls_lb_add(

View File

@ -50,7 +50,8 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
'vip_network_id': self.vip_network_id,
'admin_state_up': False}
self.ports = {'ports': [{
'fixed_ips': [{'ip_address': self.vip_address}],
'fixed_ips': [{'ip_address': self.vip_address,
'subnet_id': uuidutils.generate_uuid()}],
'network_id': self.vip_network_id,
'id': self.port1_id}]}
self.pool = {'id': self.pool_id,
@ -415,6 +416,8 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
def test_lb_create_selection_fields_not_supported_algo(self, net_cli):
self.lb['admin_state_up'] = True
net_cli.return_value.list_ports.return_value = self.ports
net_cli.return_value.show_subnet.return_value = {
'subnet': mock.MagicMock()}
self.pool['lb_algoritm'] = 'foo'
status = self.helper.lb_create(self.lb)
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
@ -1197,7 +1200,7 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
status = self.helper.member_create(self.member)
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
constants.ACTIVE)
f_lr.assert_called_once_with(self.network)
f_lr.assert_called_once_with(self.network, fake_subnet['gateway_ip'])
f_ls.assert_called_once_with(self.router)
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ls_for_lr')
@ -1801,25 +1804,35 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
lsp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={
'external_ids': {
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router1'},
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router1',
'neutron:cidrs': '10.10.10.1/24'},
'type': 'router',
'options': {
'router-port': 'lrp-foo-name'}
'router-port': 'lrp-foo-name'},
})
lsp2 = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={
'external_ids': {
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router2',
'neutron:cidrs': '10.10.10.2/24'},
'type': 'router',
'options': {
'router-port': 'lrp-bar-name'},
})
lrp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={
'name': 'lrp-foo-name'
'name': 'lrp-foo-name',
})
lr = fakes.FakeOVNRouter.create_one_router(
attrs={
'name': 'router1',
'ports': [lrp]})
ls = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={'ports': [lsp]})
attrs={'ports': [lsp2, lsp]})
(self.helper.ovn_nbdb_api.get_lrs.return_value.
execute.return_value) = [lr]
returned_lr = self.helper._find_lr_of_ls(ls)
returned_lr = self.helper._find_lr_of_ls(ls, '10.10.10.1')
self.assertEqual(lr, returned_lr)
def test__find_lr_of_ls_gw_port_id(self):