Allow to create ovn loadbalancer on dual-stack provider networks
This patch ensures that loadbalancer can be created with the VIP on the provider networks when they are dual-stack (ipv4 and ipv6 subnets). Closes-Bug: #1959903 Change-Id: Ic0e6c02defb5c98791a3c3d99ff2b7cfc0ccfe2e
This commit is contained in:
parent
a4ec59288a
commit
1ac25e8814
|
@ -28,6 +28,7 @@ OVN_DEVICE_OWNER_EXT_ID_KEY = 'neutron:device_owner'
|
||||||
OVN_FIP_EXT_ID_KEY = 'neutron:fip_id'
|
OVN_FIP_EXT_ID_KEY = 'neutron:fip_id'
|
||||||
OVN_FIP_PORT_EXT_ID_KEY = 'neutron:fip_port_id'
|
OVN_FIP_PORT_EXT_ID_KEY = 'neutron:fip_port_id'
|
||||||
OVN_GW_PORT_EXT_ID_KEY = 'neutron:gw_port_id'
|
OVN_GW_PORT_EXT_ID_KEY = 'neutron:gw_port_id'
|
||||||
|
OVN_PORT_CIDR_EXT_ID_KEY = 'neutron:cidrs'
|
||||||
|
|
||||||
LB_EXT_IDS_LS_REFS_KEY = 'ls_refs'
|
LB_EXT_IDS_LS_REFS_KEY = 'ls_refs'
|
||||||
LB_EXT_IDS_LR_REF_KEY = 'lr_ref'
|
LB_EXT_IDS_LR_REF_KEY = 'lr_ref'
|
||||||
|
|
|
@ -634,10 +634,14 @@ class OvnProviderHelper():
|
||||||
def _find_lr_of_ls(self, ovn_ls, subnet_gateway_ip=None):
|
def _find_lr_of_ls(self, ovn_ls, subnet_gateway_ip=None):
|
||||||
lsp_router_port = None
|
lsp_router_port = None
|
||||||
for port in ovn_ls.ports or []:
|
for port in ovn_ls.ports or []:
|
||||||
if port.type == 'router':
|
if (port.type == 'router' and
|
||||||
|
port.external_ids.get(
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY) ==
|
||||||
|
n_const.DEVICE_OWNER_ROUTER_INTF):
|
||||||
if subnet_gateway_ip:
|
if subnet_gateway_ip:
|
||||||
port_cidr = netaddr.IPNetwork(
|
port_cidr = netaddr.IPNetwork(
|
||||||
port.external_ids['neutron:cidrs']).ip
|
port.external_ids[
|
||||||
|
ovn_const.OVN_PORT_CIDR_EXT_ID_KEY]).ip
|
||||||
if netaddr.IPAddress(subnet_gateway_ip) != port_cidr:
|
if netaddr.IPAddress(subnet_gateway_ip) != port_cidr:
|
||||||
continue
|
continue
|
||||||
lsp_router_port = port
|
lsp_router_port = port
|
||||||
|
@ -1533,9 +1537,8 @@ class OvnProviderHelper():
|
||||||
ovn_lr = self._find_lr_of_ls(
|
ovn_lr = self._find_lr_of_ls(
|
||||||
ovn_ls, subnet['subnet'].get('gateway_ip'))
|
ovn_ls, subnet['subnet'].get('gateway_ip'))
|
||||||
if ovn_lr:
|
if ovn_lr:
|
||||||
for net in self._find_ls_for_lr(ovn_lr):
|
commands.extend(self._update_lb_to_lr_association(
|
||||||
commands.append(self.ovn_nbdb_api.ls_lb_add(
|
ovn_lb, ovn_lr))
|
||||||
net, ovn_lb.uuid, may_exist=True))
|
|
||||||
except n_exc.NotFound:
|
except n_exc.NotFound:
|
||||||
pass
|
pass
|
||||||
except idlutils.RowNotFound:
|
except idlutils.RowNotFound:
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
import copy
|
import copy
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
|
from neutron_lib import constants as n_const
|
||||||
from neutronclient.common import exceptions as n_exc
|
from neutronclient.common import exceptions as n_exc
|
||||||
from octavia_lib.api.drivers import data_models
|
from octavia_lib.api.drivers import data_models
|
||||||
from octavia_lib.api.drivers import exceptions
|
from octavia_lib.api.drivers import exceptions
|
||||||
|
@ -1215,20 +1216,22 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
|
||||||
self.assertEqual(status['members'][0]['operating_status'],
|
self.assertEqual(status['members'][0]['operating_status'],
|
||||||
constants.OFFLINE)
|
constants.OFFLINE)
|
||||||
|
|
||||||
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ls_for_lr')
|
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ovn_lb_by_pool_id')
|
||||||
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_lr_of_ls')
|
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_lr_of_ls')
|
||||||
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
|
@mock.patch('ovn_octavia_provider.common.clients.get_neutron_client')
|
||||||
def test_member_create_lb_add_from_lr(self, net_cli, f_lr, f_ls):
|
def test_member_create_lb_add_from_lr(self, net_cli, f_lr, folbpi):
|
||||||
fake_subnet = fakes.FakeSubnet.create_one_subnet()
|
fake_subnet = fakes.FakeSubnet.create_one_subnet()
|
||||||
net_cli.return_value.show_subnet.return_value = {'subnet': fake_subnet}
|
net_cli.return_value.show_subnet.return_value = {'subnet': fake_subnet}
|
||||||
f_lr.return_value = self.router
|
f_lr.return_value = self.router
|
||||||
f_ls.return_value = [self.network]
|
pool_key = 'pool_%s' % self.pool_id
|
||||||
|
folbpi.return_value = (pool_key, self.ovn_lb)
|
||||||
self.ovn_lb.external_ids = mock.MagicMock()
|
self.ovn_lb.external_ids = mock.MagicMock()
|
||||||
status = self.helper.member_create(self.member)
|
status = self.helper.member_create(self.member)
|
||||||
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
|
self.assertEqual(status['loadbalancers'][0]['provisioning_status'],
|
||||||
constants.ACTIVE)
|
constants.ACTIVE)
|
||||||
f_lr.assert_called_once_with(self.network, fake_subnet['gateway_ip'])
|
f_lr.assert_called_once_with(self.network, fake_subnet['gateway_ip'])
|
||||||
f_ls.assert_called_once_with(self.router)
|
self.helper._update_lb_to_lr_association.assert_called_once_with(
|
||||||
|
self.ovn_lb, self.router)
|
||||||
|
|
||||||
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ls_for_lr')
|
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_ls_for_lr')
|
||||||
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_lr_of_ls')
|
@mock.patch.object(ovn_helper.OvnProviderHelper, '_find_lr_of_ls')
|
||||||
|
@ -1832,7 +1835,9 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
|
||||||
attrs={
|
attrs={
|
||||||
'external_ids': {
|
'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'},
|
'neutron:cidrs': '10.10.10.1/24',
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
|
||||||
|
n_const.DEVICE_OWNER_ROUTER_INTF},
|
||||||
'type': 'router',
|
'type': 'router',
|
||||||
'options': {
|
'options': {
|
||||||
'router-port': 'lrp-foo-name'},
|
'router-port': 'lrp-foo-name'},
|
||||||
|
@ -1841,7 +1846,9 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
|
||||||
attrs={
|
attrs={
|
||||||
'external_ids': {
|
'external_ids': {
|
||||||
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router2',
|
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router2',
|
||||||
'neutron:cidrs': '10.10.10.2/24'},
|
'neutron:cidrs': '10.10.10.2/24',
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
|
||||||
|
n_const.DEVICE_OWNER_ROUTER_INTF},
|
||||||
'type': 'router',
|
'type': 'router',
|
||||||
'options': {
|
'options': {
|
||||||
'router-port': 'lrp-bar-name'},
|
'router-port': 'lrp-bar-name'},
|
||||||
|
@ -1866,7 +1873,9 @@ class TestOvnProviderHelper(ovn_base.TestOvnOctaviaBase):
|
||||||
lsp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
|
lsp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
|
||||||
attrs={
|
attrs={
|
||||||
'external_ids': {
|
'external_ids': {
|
||||||
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router1'},
|
ovn_const.OVN_ROUTER_NAME_EXT_ID_KEY: 'router1',
|
||||||
|
ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
|
||||||
|
n_const.DEVICE_OWNER_ROUTER_INTF},
|
||||||
'type': 'router',
|
'type': 'router',
|
||||||
'options': {
|
'options': {
|
||||||
'router-port': 'lrp-lrp-foo-name'}
|
'router-port': 'lrp-lrp-foo-name'}
|
||||||
|
|
Loading…
Reference in New Issue