Merge "Add support to PF OVN LBs for NB Driver"
This commit is contained in:
commit
8d3273f6c6
@ -36,11 +36,17 @@ OVN_DEVICE_OWNER_EXT_ID_KEY = 'neutron:device_owner'
|
||||
OVN_FIP_EXT_ID_KEY = 'neutron:port_fip'
|
||||
OVN_FIP_NET_EXT_ID_KEY = 'neutron:fip_network_id'
|
||||
LB_VIP_PORT_PREFIX = "ovn-lb-vip-"
|
||||
OVN_LB_PF_NAME_PREFIX = "pf-floatingip-"
|
||||
OVN_LB_VIP_IP_EXT_ID_KEY = 'neutron:vip'
|
||||
OVN_LB_VIP_FIP_EXT_ID_KEY = 'neutron:vip_fip'
|
||||
OVN_LB_VIP_PORT_EXT_ID_KEY = 'neutron:vip_port_id'
|
||||
OVN_LB_LR_REF_EXT_ID_KEY = 'lr_ref'
|
||||
|
||||
OVN_LB_EXT_ID_ROUTER_KEY = [
|
||||
OVN_LB_LR_REF_EXT_ID_KEY,
|
||||
OVN_LR_NAME_EXT_ID_KEY
|
||||
]
|
||||
|
||||
OVS_RULE_COOKIE = "999"
|
||||
OVS_VRF_RULE_COOKIE = "998"
|
||||
|
||||
|
@ -145,7 +145,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
||||
watcher.LogicalSwitchPortFIPDeleteEvent(self),
|
||||
watcher.LocalnetCreateDeleteEvent(self),
|
||||
watcher.OVNLBCreateEvent(self),
|
||||
watcher.OVNLBDeleteEvent(self)}
|
||||
watcher.OVNLBDeleteEvent(self),
|
||||
watcher.OVNPFCreateEvent(self),
|
||||
watcher.OVNPFDeleteEvent(self)}
|
||||
if self._expose_tenant_networks:
|
||||
events.update({watcher.ChassisRedirectCreateEvent(self),
|
||||
watcher.ChassisRedirectDeleteEvent(self),
|
||||
@ -332,18 +334,24 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
||||
def _expose_lbs(self, router_list):
|
||||
lbs = self.nb_idl.get_active_local_lbs(router_list)
|
||||
for lb in lbs:
|
||||
self._expose_ovn_lb_vip(lb)
|
||||
# if vip-fip expose fip too
|
||||
if lb.external_ids.get(constants.OVN_LB_VIP_FIP_EXT_ID_KEY):
|
||||
self._expose_ovn_lb_fip(lb)
|
||||
if driver_utils.is_pf_lb(lb):
|
||||
self._expose_ovn_pf_lb_fip(lb)
|
||||
else:
|
||||
self._expose_ovn_lb_vip(lb)
|
||||
# if vip-fip expose fip too
|
||||
if lb.external_ids.get(constants.OVN_LB_VIP_FIP_EXT_ID_KEY):
|
||||
self._expose_ovn_lb_fip(lb)
|
||||
|
||||
def _withdraw_lbs(self, router_list):
|
||||
lbs = self.nb_idl.get_active_local_lbs(router_list)
|
||||
for lb in lbs:
|
||||
self._withdraw_ovn_lb_vip(lb)
|
||||
# if vip-fip withdraw fip too
|
||||
if lb.external_ids.get(constants.OVN_LB_VIP_FIP_EXT_ID_KEY):
|
||||
self._withdraw_ovn_lb_fip(lb)
|
||||
if driver_utils.is_pf_lb(lb):
|
||||
self._withdraw_ovn_pf_lb_fip(lb)
|
||||
else:
|
||||
self._withdraw_ovn_lb_vip(lb)
|
||||
# if vip-fip withdraw fip too
|
||||
if lb.external_ids.get(constants.OVN_LB_VIP_FIP_EXT_ID_KEY):
|
||||
self._withdraw_ovn_lb_fip(lb)
|
||||
|
||||
@lockutils.synchronized('nbbgp')
|
||||
def expose_ip(self, ips, ips_info):
|
||||
@ -841,6 +849,50 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
||||
return
|
||||
self._expose_fip(external_ip, external_mac, ls_name, vip_lsp)
|
||||
|
||||
def _get_parameters_from_lb(self, lb, include_mac_and_localnet=False):
|
||||
for fipport in lb.vips.keys():
|
||||
fip, port = fipport.split(':')
|
||||
break
|
||||
else:
|
||||
return
|
||||
|
||||
router = lb.external_ids.get(
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY, '').replace('neutron-', "", 1)
|
||||
if not router:
|
||||
return
|
||||
cr_lrp_info = self.ovn_local_cr_lrps.get(router)
|
||||
if not cr_lrp_info:
|
||||
return
|
||||
net, bridge_device, bridge_vlan = self._get_ls_localnet_info(
|
||||
cr_lrp_info['provider_switch'])
|
||||
kwargs = {
|
||||
'port_ips': [fip],
|
||||
'logical_switch': cr_lrp_info['provider_switch'],
|
||||
'bridge_device': bridge_device,
|
||||
'bridge_vlan': bridge_vlan}
|
||||
|
||||
if include_mac_and_localnet:
|
||||
kwargs['mac'] = None
|
||||
kwargs['localnet'] = net
|
||||
|
||||
return kwargs
|
||||
|
||||
@lockutils.synchronized('nbbgp')
|
||||
def expose_ovn_pf_lb_fip(self, lb):
|
||||
self._expose_ovn_pf_lb_fip(lb)
|
||||
|
||||
@lockutils.synchronized('nbbgp')
|
||||
def withdraw_ovn_pf_lb_fip(self, lb):
|
||||
self._withdraw_ovn_pf_lb_fip(lb)
|
||||
|
||||
def _withdraw_ovn_pf_lb_fip(self, lb):
|
||||
kwargs = self._get_parameters_from_lb(lb)
|
||||
self._withdraw_provider_port(**kwargs) if kwargs else None
|
||||
|
||||
def _expose_ovn_pf_lb_fip(self, lb):
|
||||
kwargs = self._get_parameters_from_lb(lb, True)
|
||||
self._expose_provider_port(**kwargs) if kwargs else None
|
||||
|
||||
@lockutils.synchronized('nbbgp')
|
||||
def withdraw_ovn_lb_fip(self, lb):
|
||||
self._withdraw_ovn_lb_fip(lb)
|
||||
|
@ -38,3 +38,14 @@ def get_addr_scopes(port):
|
||||
constants.IP_VERSION_6: port.external_ids.get(
|
||||
constants.SUBNET_POOL_ADDR_SCOPE6),
|
||||
}
|
||||
|
||||
|
||||
def check_name_prefix(entity, prefix):
|
||||
try:
|
||||
return entity.name.startswith(prefix)
|
||||
except AttributeError:
|
||||
return False
|
||||
|
||||
|
||||
def is_pf_lb(lb):
|
||||
return check_name_prefix(lb, constants.OVN_LB_PF_NAME_PREFIX)
|
||||
|
@ -470,11 +470,17 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
|
||||
def get_active_local_lbs(self, local_gateway_ports):
|
||||
lbs = []
|
||||
cmd = self.db_find_rows('Load_Balancer', ('vips', '!=', {}))
|
||||
|
||||
for row in cmd.execute(check_error=True):
|
||||
if (row.vips and row.external_ids[
|
||||
constants.OVN_LB_LR_REF_EXT_ID_KEY].replace(
|
||||
'neutron-', "", 1) in local_gateway_ports):
|
||||
lbs.append(row)
|
||||
for ext_id_key in constants.OVN_LB_EXT_ID_ROUTER_KEY:
|
||||
try:
|
||||
router_name = row.external_ids[ext_id_key].replace(
|
||||
'neutron-', '', 1)
|
||||
if router_name in local_gateway_ports:
|
||||
lbs.append(row)
|
||||
break
|
||||
except KeyError:
|
||||
continue
|
||||
return lbs
|
||||
|
||||
# FIXME(ltomasbo): This can be removed once ovsdbapp version is >=2.3.0
|
||||
|
@ -50,10 +50,9 @@ class OVNLBEvent(Event):
|
||||
events, table, None)
|
||||
self.event_name = self.__class__.__name__
|
||||
|
||||
def _get_router(self, row):
|
||||
def _get_router(self, row, key=constants.OVN_LB_LR_REF_EXT_ID_KEY):
|
||||
try:
|
||||
return row.external_ids[
|
||||
constants.OVN_LB_LR_REF_EXT_ID_KEY].replace('neutron-', "", 1)
|
||||
return row.external_ids[key].replace('neutron-', "", 1)
|
||||
except (AttributeError, KeyError):
|
||||
return
|
||||
|
||||
|
@ -728,3 +728,43 @@ class OVNLBDeleteEvent(base_watcher.OVNLBEvent):
|
||||
|
||||
if hasattr(old, 'vips'):
|
||||
self.agent.withdraw_ovn_lb_vip(row)
|
||||
|
||||
|
||||
class OVNPFBaseEvent(base_watcher.OVNLBEvent):
|
||||
|
||||
event = None
|
||||
|
||||
def __init__(self, bgp_agent):
|
||||
super(OVNPFBaseEvent, self).__init__(
|
||||
bgp_agent, (self.event,))
|
||||
|
||||
def match_fn(self, event, row, old):
|
||||
# The ovn port forwarding are manage as OVN lb balancers and they are
|
||||
# exposed through the cr-lrp, so if the local agent does not have the
|
||||
# matching router there is no need to process the event
|
||||
if not driver_utils.check_name_prefix(row,
|
||||
constants.OVN_LB_PF_NAME_PREFIX):
|
||||
return False
|
||||
|
||||
if not row.vips:
|
||||
return False
|
||||
lb_router = self._get_router(row, constants.OVN_LR_NAME_EXT_ID_KEY)
|
||||
return lb_router in self.agent.ovn_local_cr_lrps.keys()
|
||||
|
||||
|
||||
class OVNPFCreateEvent(OVNPFBaseEvent):
|
||||
|
||||
event = OVNPFBaseEvent.ROW_CREATE
|
||||
|
||||
def _run(self, event, row, old):
|
||||
with _SYNC_STATE_LOCK.read_lock():
|
||||
self.agent.expose_ovn_pf_lb_fip(row)
|
||||
|
||||
|
||||
class OVNPFDeleteEvent(OVNPFBaseEvent):
|
||||
|
||||
event = OVNPFBaseEvent.ROW_DELETE
|
||||
|
||||
def _run(self, event, row, old):
|
||||
with _SYNC_STATE_LOCK.read_lock():
|
||||
self.agent.withdraw_ovn_pf_lb_fip(row)
|
||||
|
@ -1286,6 +1286,55 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
||||
mock_withdraw_remote_ip.assert_not_called()
|
||||
mock_withdraw_provider_port.assert_not_called()
|
||||
|
||||
def test_expose_ovn_pf_lb_fip(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY: 'neutron-router1'},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_get_ls_localnet_info = mock.patch.object(
|
||||
self.nb_bgp_driver, '_get_ls_localnet_info').start()
|
||||
mock_get_ls_localnet_info.return_value = ('provider-ls', 'br-ex',
|
||||
100)
|
||||
mock_expose_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_expose_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.expose_ovn_pf_lb_fip(lb)
|
||||
kwargs = {
|
||||
'port_ips': ['fip'],
|
||||
'mac': None,
|
||||
'logical_switch': 'provider-ls',
|
||||
'bridge_device': 'br-ex',
|
||||
'bridge_vlan': 100,
|
||||
'localnet': 'provider-ls'}
|
||||
mock_expose_provider_port.assert_called_once_with(**kwargs)
|
||||
|
||||
def test_expose_ovn_pf_lb_fip_no_router(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_expose_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_expose_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.expose_ovn_pf_lb_fip(lb)
|
||||
mock_expose_provider_port.assert_not_called()
|
||||
|
||||
def test_expose_ovn_pf_lb_fip_no_router_cr_lrp(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY: 'neutron-router2'},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_expose_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_expose_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.expose_ovn_pf_lb_fip(lb)
|
||||
mock_expose_provider_port.assert_not_called()
|
||||
|
||||
def test_expose_ovn_lb_fip(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={
|
||||
@ -1391,3 +1440,50 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
||||
|
||||
self.nb_bgp_driver.withdraw_ovn_lb_fip(lb)
|
||||
mock_withdraw_provider_port.assert_not_called()
|
||||
|
||||
def test_withdraw_ovn_pf_lb_fip(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY: 'neutron-router1'},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_get_ls_localnet_info = mock.patch.object(
|
||||
self.nb_bgp_driver, '_get_ls_localnet_info').start()
|
||||
mock_get_ls_localnet_info.return_value = ('provider-ls', 'br-ex', 100)
|
||||
|
||||
mock_withdraw_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_withdraw_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.withdraw_ovn_pf_lb_fip(lb)
|
||||
kwargs = {
|
||||
'port_ips': ['fip'],
|
||||
'logical_switch': 'provider-ls',
|
||||
'bridge_device': 'br-ex',
|
||||
'bridge_vlan': 100}
|
||||
mock_withdraw_provider_port.assert_called_once_with(**kwargs)
|
||||
|
||||
def test_withdraw_ovn_pf_lb_fip_no_router(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_withdraw_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_withdraw_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.withdraw_ovn_pf_lb_fip(lb)
|
||||
mock_withdraw_provider_port.assert_not_called()
|
||||
|
||||
def test_withdraw_ovn_pf_lb_fip_no_cr_lrp(self):
|
||||
lb = utils.create_row(
|
||||
external_ids={
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY: 'neutron-router2'},
|
||||
name='pf-floatingip-uuid-tcp',
|
||||
vips={'fip:port': 'member:port'})
|
||||
|
||||
mock_withdraw_provider_port = mock.patch.object(
|
||||
self.nb_bgp_driver, '_withdraw_provider_port').start()
|
||||
|
||||
self.nb_bgp_driver.withdraw_ovn_pf_lb_fip(lb)
|
||||
mock_withdraw_provider_port.assert_not_called()
|
||||
|
@ -221,6 +221,19 @@ class TestOvsdbNbOvnIdl(test_base.TestCase):
|
||||
self.nb_idl.db_find_rows.assert_called_once_with(
|
||||
'Load_Balancer', ('vips', '!=', {}))
|
||||
|
||||
self.nb_idl.db_find_rows.reset_mock()
|
||||
|
||||
lb3 = fakes.create_object({
|
||||
'vips': {'fip': 'member1'},
|
||||
'external_ids': {
|
||||
constants.OVN_LR_NAME_EXT_ID_KEY: "neutron-router1"}})
|
||||
self.nb_idl.db_find_rows.return_value.execute.return_value = [
|
||||
lb1, lb2, lb3]
|
||||
ret = self.nb_idl.get_active_local_lbs(local_gateway_ports)
|
||||
self.assertEqual([lb1, lb3], ret)
|
||||
self.nb_idl.db_find_rows.assert_called_once_with(
|
||||
'Load_Balancer', ('vips', '!=', {}))
|
||||
|
||||
|
||||
class TestOvsdbSbOvnIdl(test_base.TestCase):
|
||||
|
||||
|
@ -59,7 +59,13 @@ class TestOVNLBEvent(test_base.TestCase):
|
||||
def test__get_router(self):
|
||||
row = utils.create_row(
|
||||
external_ids={constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-net'})
|
||||
self.assertEqual('net', self.ovnlb_event._get_router(
|
||||
row, constants.OVN_LB_LR_REF_EXT_ID_KEY))
|
||||
self.assertEqual('net', self.ovnlb_event._get_router(row))
|
||||
row = utils.create_row(
|
||||
external_ids={constants.OVN_LR_NAME_EXT_ID_KEY: 'neutron-router1'})
|
||||
self.assertEqual('router1', self.ovnlb_event._get_router(
|
||||
row, constants.OVN_LR_NAME_EXT_ID_KEY))
|
||||
row = utils.create_row(external_ids={})
|
||||
self.assertEqual(None, self.ovnlb_event._get_router(row))
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user