Add support at NB BGP Driver for exposing OVN LBs

Change-Id: I4b1992d938e157a693c9db33882e5bc27ef8f604
This commit is contained in:
Luis Tomas Bolivar 2023-10-27 16:33:40 +02:00
parent aaa0ae0c1a
commit bb663ad778
12 changed files with 949 additions and 60 deletions

View File

@ -140,7 +140,7 @@ The folloging events are watched and handled by the BGP watcher:
The BGP watcher detects OVN Southbound Database events at the ``Port_Binding``
and ``Load_Balancer`` tables. It creates new event classes named
``PortBindingChassisEvent`` and ``OVNLBMemberEvent``, that all the events
``PortBindingChassisEvent`` and ``OVNLBEvent``, that all the events
watched for BGP use as the base (inherit from).
The specific defined events to react to are:

View File

@ -79,7 +79,7 @@ networking accordingly.
The BGP watcher detects OVN Southbound Database events at the ``Port_Binding``
and ``Load_Balancer`` tables. It creates new event classes named
``PortBindingChassisEvent`` and ``OVNLBMemberEvent``, that all the events
``PortBindingChassisEvent`` and ``OVNLBEvent``, that all the events
watched for BGP use as the base (inherit from).
The driver react specifically to the following events:

View File

@ -33,6 +33,10 @@ 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_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'
OVS_RULE_COOKIE = "999"
OVS_VRF_RULE_COOKIE = "998"

View File

@ -36,7 +36,7 @@ LOG = logging.getLogger(__name__)
# logging.basicConfig(level=logging.DEBUG)
OVN_TABLES = ['Logical_Switch_Port', 'NAT', 'Logical_Switch',
'Logical_Router_Port']
'Logical_Router_Port', 'Load_Balancer']
LOCAL_CLUSTER_OVN_TABLES = ['Logical_Switch', 'Logical_Switch_Port',
'Logical_Router', 'Logical_Router_Port',
'Logical_Router_Policy',
@ -146,7 +146,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
"LogicalSwitchPortProviderDeleteEvent",
"LogicalSwitchPortFIPCreateEvent",
"LogicalSwitchPortFIPDeleteEvent",
"LocalnetCreateDeleteEvent"])
"LocalnetCreateDeleteEvent",
"OVNLBCreateEvent",
"OVNLBDeleteEvent"])
if self._expose_tenant_networks:
events.update(["ChassisRedirectCreateEvent",
"ChassisRedirectDeleteEvent",
@ -202,6 +204,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
continue
self._ensure_lsp_exposed(port)
# add missing routes/ips for OVN loadbalancers
self._expose_lbs(self.ovn_local_cr_lrps.keys())
# remove extra wiring leftovers
wire_utils.cleanup_wiring(self.nb_idl,
self.ovn_bridge_mappings,
@ -323,6 +328,22 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
bridge_vlan = localnet.tag[0]
return bridge_device, bridge_vlan
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)
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)
@lockutils.synchronized('nbbgp')
def expose_ip(self, ips, ips_info):
'''Advertice BGP route by adding IP to device.
@ -339,20 +360,28 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
logical_switch = ips_info.get('logical_switch')
if not logical_switch:
return False
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
logical_switch)
if not bridge_device:
# This means it is not a provider network
self.ovn_tenant_ls[logical_switch] = True
return False
if bridge_device not in self.ovn_bridge_mappings.values():
# This node is not properly configured, no need to expose it
return False
if not self.ovn_provider_ls.get(logical_switch):
self.ovn_provider_ls[logical_switch] = {
'bridge_device': bridge_device,
'bridge_vlan': bridge_vlan,
'localnet': localnet}
bridge_info = self.ovn_provider_ls.get(logical_switch)
if bridge_info:
# already known provider ls
bridge_device = bridge_info['bridge_device']
bridge_vlan = bridge_info['bridge_vlan']
localnet = bridge_info['localnet']
else:
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
logical_switch)
if not bridge_device:
# This means it is not a provider network
self.ovn_tenant_ls[logical_switch] = True
return False
if bridge_device not in self.ovn_bridge_mappings.values():
# This node is not properly configured, no need to expose it
return False
if not self.ovn_provider_ls.get(logical_switch):
self.ovn_provider_ls[logical_switch] = {
'bridge_device': bridge_device,
'bridge_vlan': bridge_vlan,
'localnet': localnet}
mac = ips_info.get('mac')
return self._expose_ip(ips, mac, logical_switch, bridge_device,
bridge_vlan, port_type=ips_info['type'],
@ -379,6 +408,7 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
self.ovn_local_cr_lrps[router] = {
'bridge_device': bridge_device,
'bridge_vlan': bridge_vlan,
'provider_switch': logical_switch,
'ips': ips,
}
# Expose associated subnets
@ -393,6 +423,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
constants.OVN_LS_NAME_EXT_ID_KEY),
'address_scopes': driver_utils.get_addr_scopes(port)}
self._expose_subnet(ips, subnet_info)
# add missing routes/ips for OVN loadbalancers
self._expose_lbs([router])
else:
if not self._expose_provider_port(ips, mac, logical_switch,
bridge_device, bridge_vlan,
@ -452,6 +485,10 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
constants.OVN_LS_NAME_EXT_ID_KEY),
'address_scopes': driver_utils.get_addr_scopes(port)}
self._withdraw_subnet(ips, subnet_info)
# withdraw routes/ips for OVN loadbalancers
self._withdraw_lbs([ips_info['router']])
try:
del self.ovn_local_cr_lrps[ips_info['router']]
except KeyError:
@ -497,19 +534,26 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
return self._expose_fip(ip, mac, logical_switch, row)
def _expose_fip(self, ip, mac, logical_switch, row):
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
logical_switch)
if not bridge_device:
# This means it is not a provider network
return False
if bridge_device not in self.ovn_bridge_mappings.values():
# This node is not properly configured, no need to expose it
return False
if not self.ovn_provider_ls.get(logical_switch):
self.ovn_provider_ls[logical_switch] = {
'bridge_device': bridge_device,
'bridge_vlan': bridge_vlan,
'localnet': localnet}
bridge_info = self.ovn_provider_ls.get(logical_switch)
if bridge_info:
# already known provider ls
bridge_device = bridge_info['bridge_device']
bridge_vlan = bridge_info['bridge_vlan']
localnet = bridge_info['localnet']
else:
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
logical_switch)
if not bridge_device:
# This means it is not a provider network
return False
if bridge_device not in self.ovn_bridge_mappings.values():
# This node is not properly configured, no need to expose it
return False
if not self.ovn_provider_ls.get(logical_switch):
self.ovn_provider_ls[logical_switch] = {
'bridge_device': bridge_device,
'bridge_vlan': bridge_vlan,
'localnet': localnet}
tenant_logical_switch = row.external_ids.get(
constants.OVN_LS_NAME_EXT_ID_KEY)
if not tenant_logical_switch:
@ -556,6 +600,10 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
def expose_remote_ip(self, ips, ips_info):
self._expose_remote_ip(ips, ips_info)
@lockutils.synchronized('nbbgp')
def withdraw_remote_ip(self, ips, ips_info):
self._withdraw_remote_ip(ips, ips_info)
def _expose_remote_ip(self, ips, ips_info):
ips_to_expose = ips
if not CONF.expose_tenant_networks:
@ -574,10 +622,6 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
LOG.debug("Added BGP route for tenant IP(s) %s on chassis %s",
ips_to_expose, self.chassis)
@lockutils.synchronized('nbbgp')
def withdraw_remote_ip(self, ips, ips_info):
self._withdraw_remote_ip(ips, ips_info)
def _withdraw_remote_ip(self, ips, ips_info):
ips_to_withdraw = ips
if not CONF.expose_tenant_networks:
@ -737,6 +781,95 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
pass
return True
@lockutils.synchronized('nbbgp')
def expose_ovn_lb_vip(self, lb):
self._expose_ovn_lb_vip(lb)
def _expose_ovn_lb_vip(self, lb):
vip_port = lb.external_ids.get(constants.OVN_LB_VIP_PORT_EXT_ID_KEY)
vip_ip = lb.external_ids.get(constants.OVN_LB_VIP_IP_EXT_ID_KEY)
vip_router = lb.external_ids[
constants.OVN_LB_LR_REF_EXT_ID_KEY].replace('neutron-', "", 1)
vip_lsp = self.nb_idl.lsp_get(vip_port).execute(check_error=True)
if not vip_lsp:
LOG.debug("Something went wrong, VIP port %s not found", vip_port)
return
vip_net = vip_lsp.external_ids.get(constants.OVN_LS_NAME_EXT_ID_KEY)
if vip_net in self.ovn_local_lrps.keys():
# It is a VIP on a tenant network
# NOTE: the LB is exposed through the cr-lrp, so we add the
# vip_router instead of the logical switch
ips_info = {'logical_switch': vip_router}
self._expose_remote_ip([vip_ip], ips_info)
else:
# It is a VIP on a provider network
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
vip_net)
self._expose_provider_port([vip_ip], None, vip_net, bridge_device,
bridge_vlan, localnet)
@lockutils.synchronized('nbbgp')
def withdraw_ovn_lb_vip(self, lb):
self._withdraw_ovn_lb_vip(lb)
def _withdraw_ovn_lb_vip(self, lb):
vip_ip = lb.external_ids.get(constants.OVN_LB_VIP_IP_EXT_ID_KEY)
vip_router = lb.external_ids[
constants.OVN_LB_LR_REF_EXT_ID_KEY].replace('neutron-', "", 1)
cr_lrp_info = self.ovn_local_cr_lrps.get(vip_router)
if not cr_lrp_info:
return
provider_ls = cr_lrp_info['provider_switch']
if self._exposed_ips.get(provider_ls, {}).get(vip_ip):
# VIP is on provider network
self._withdraw_provider_port([vip_ip],
cr_lrp_info['provider_switch'],
cr_lrp_info['bridge_device'],
cr_lrp_info['bridge_vlan'])
else:
# VIP is on tenant network
ips_info = {'logical_switch': vip_router}
self._withdraw_remote_ip([vip_ip], ips_info)
@lockutils.synchronized('nbbgp')
def expose_ovn_lb_fip(self, lb):
self._expose_ovn_lb_fip(lb)
def _expose_ovn_lb_fip(self, lb):
vip_port = lb.external_ids.get(constants.OVN_LB_VIP_PORT_EXT_ID_KEY)
vip_lsp = self.nb_idl.lsp_get(vip_port).execute(check_error=True)
if not vip_lsp:
LOG.debug("Something went wrong, VIP port %s not found", vip_port)
return
external_ip, external_mac, ls_name = (
self.get_port_external_ip_and_ls(vip_lsp.name))
if not external_ip or not ls_name:
LOG.debug("Something went wrong, no NAT entry for the VIP %s",
vip_port)
return
self._expose_fip(external_ip, external_mac, ls_name, vip_lsp)
@lockutils.synchronized('nbbgp')
def withdraw_ovn_lb_fip(self, lb):
self._withdraw_ovn_lb_fip(lb)
def _withdraw_ovn_lb_fip(self, lb):
vip_fip = lb.external_ids.get(constants.OVN_LB_VIP_FIP_EXT_ID_KEY)
# OVN loadbalancers ARPs are replied by router port
vip_router = lb.external_ids.get(
constants.OVN_LB_LR_REF_EXT_ID_KEY, "").replace('neutron-', "", 1)
if not vip_router:
return
cr_lrp_info = self.ovn_local_cr_lrps.get(vip_router)
if not cr_lrp_info:
return
self._withdraw_provider_port([vip_fip],
cr_lrp_info['provider_switch'],
cr_lrp_info['bridge_device'],
cr_lrp_info['bridge_vlan'])
def _address_scope_allowed(self, ip, address_scopes):
if not self.allowed_address_scopes:
# No address scopes to filter on => announce everything

View File

@ -467,6 +467,16 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
ports.extend(cmd.execute(check_error=True))
return ports
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)
return lbs
# FIXME(ltomasbo): This can be removed once ovsdbapp version is >=2.3.0
def ls_get_localnet_ports(self, logical_switch, if_exists=True):
return LSGetLocalnetPortsCommand(self, logical_switch,

View File

@ -42,14 +42,27 @@ class PortBindingChassisEvent(Event):
return len(mac.strip().split(' ')) > 1
class OVNLBMemberEvent(Event):
class OVNLBEvent(Event):
def __init__(self, bgp_agent, events):
self.agent = bgp_agent
table = 'Load_Balancer'
super(OVNLBMemberEvent, self).__init__(
super(OVNLBEvent, self).__init__(
events, table, None)
self.event_name = self.__class__.__name__
def _get_router(self, row):
try:
return row.external_ids[
constants.OVN_LB_LR_REF_EXT_ID_KEY].replace('neutron-', "", 1)
except (AttributeError, KeyError):
return
def _get_vip_fip(self, row):
try:
return row.external_ids[constants.OVN_LB_VIP_FIP_EXT_ID_KEY]
except (AttributeError, KeyError):
return
class LSPChassisEvent(Event):
def __init__(self, bgp_agent, events):
@ -74,10 +87,10 @@ class LSPChassisEvent(Event):
return None, None
def _get_network(self, row):
if (hasattr(row, 'external_ids') and
row.external_ids.get(constants.OVN_LS_NAME_EXT_ID_KEY)):
try:
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
return None
except (AttributeError, KeyError):
return
class LRPChassisEvent(Event):
@ -89,7 +102,7 @@ class LRPChassisEvent(Event):
self.event_name = self.__class__.__name__
def _get_network(self, row):
if (hasattr(row, 'external_ids') and
row.external_ids.get(constants.OVN_LS_NAME_EXT_ID_KEY)):
try:
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
return None
except (AttributeError, KeyError):
return

View File

@ -372,7 +372,7 @@ class OVNLBVIPPortEvent(base_watcher.PortBindingChassisEvent):
self.agent.expose_ovn_lb(ovn_lb_ip, row)
class OVNLBMemberCreateEvent(base_watcher.OVNLBMemberEvent):
class OVNLBMemberCreateEvent(base_watcher.OVNLBEvent):
def __init__(self, bgp_agent):
events = (self.ROW_CREATE,)
super(OVNLBMemberCreateEvent, self).__init__(
@ -445,7 +445,7 @@ class OVNLBMemberCreateEvent(base_watcher.OVNLBMemberEvent):
vip_ip, row.name, associated_cr_lrp_port)
class OVNLBMemberDeleteEvent(base_watcher.OVNLBMemberEvent):
class OVNLBMemberDeleteEvent(base_watcher.OVNLBEvent):
def __init__(self, bgp_agent):
events = (self.ROW_DELETE,)
super(OVNLBMemberDeleteEvent, self).__init__(

View File

@ -616,3 +616,122 @@ class LogicalSwitchPortTenantDeleteEvent(base_watcher.LSPChassisEvent):
'logical_switch': self._get_network(row)
}
self.agent.withdraw_remote_ip(ips, ips_info)
class OVNLBCreateEvent(base_watcher.OVNLBEvent):
def __init__(self, bgp_agent):
events = (self.ROW_UPDATE,)
super(OVNLBCreateEvent, self).__init__(
bgp_agent, events)
def match_fn(self, event, row, old):
# The ovn lb balancers 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
try:
if not row.vips:
return False
lb_router = self._get_router(row)
if lb_router not in self.agent.ovn_local_cr_lrps.keys():
return False
# Only expose if there is a modification in the VIPS
# And only expose if it is the first item on VIPs
if hasattr(old, 'vips'):
if not old.vips and row.vips:
return True
if hasattr(old, 'external_ids'):
# Check if the lb_router was added
old_lb_router = self._get_router(old)
if lb_router != old_lb_router:
return True
# Also check if there is a vip_fip addition to expose the FIP
vip_fip = self._get_vip_fip(row)
if not vip_fip:
return False
old_vip_fip = self._get_vip_fip(old)
if vip_fip != old_vip_fip:
return True
except (IndexError, AttributeError):
return False
return False
def _run(self, event, row, old):
vip_fip = self._get_vip_fip(row)
old_vip_fip = self._get_vip_fip(old)
with _SYNC_STATE_LOCK.read_lock():
if hasattr(old, 'external_ids'):
if vip_fip and vip_fip != old_vip_fip:
self.agent.expose_ovn_lb_fip(row)
else:
self.agent.expose_ovn_lb_vip(row)
class OVNLBDeleteEvent(base_watcher.OVNLBEvent):
def __init__(self, bgp_agent):
events = (self.ROW_DELETE, self.ROW_UPDATE)
super(OVNLBDeleteEvent, self).__init__(
bgp_agent, events)
def match_fn(self, event, row, old):
# The ovn lb balancers 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
try:
if event == self.ROW_DELETE:
if not row.vips:
return False
lb_router = self._get_router(row)
if lb_router in self.agent.ovn_local_cr_lrps.keys():
return True
return False
# ROW UPDATE EVENT
lb_router = self._get_router(row)
old_external_ids = False
if hasattr(old, 'external_ids'):
old_external_ids = True
old_lb_router = self._get_router(old)
if not old_lb_router:
return False
if old_lb_router not in self.agent.ovn_local_cr_lrps.keys():
return False
if old_lb_router != lb_router:
# Router should not be removed, but if that is the case we
# should remove the loadbalancer
return True
# Also check if the vip_fip is removed to withdraw the FIP
vip_fip = self._get_vip_fip(row)
old_vip_fip = self._get_vip_fip(old)
if old_vip_fip and old_vip_fip != vip_fip:
return True
# Withdraw IP if VIPs is removed
if hasattr(old, 'vips'):
if old.vips and not row.vips:
if old_external_ids:
old_lb_router = self._get_router(old)
return (old_lb_router in
self.agent.ovn_local_cr_lrps.keys())
else:
return (lb_router in
self.agent.ovn_local_cr_lrps.keys())
except (IndexError, AttributeError):
return False
return False
def _run(self, event, row, old):
vip_fip = self._get_vip_fip(row)
old_vip_fip = self._get_vip_fip(old)
with _SYNC_STATE_LOCK.read_lock():
if event == self.ROW_DELETE:
self.agent.withdraw_ovn_lb_vip(row)
if vip_fip:
self.agent.withdraw_ovn_lb_fip(row)
else:
if not vip_fip and vip_fip != old_vip_fip:
self.agent.withdraw_ovn_lb_fip(old)
if hasattr(old, 'vips'):
self.agent.withdraw_ovn_lb_vip(row)

View File

@ -59,7 +59,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
self.router1_info = {'bridge_device': self.bridge,
'bridge_vlan': 100,
'ips': ['172.24.4.11']}
'ips': ['172.24.4.11'],
'provider_switch': 'provider-ls'}
self.nb_bgp_driver.ovn_local_cr_lrps = {
'router1': self.router1_info}
self.ovn_routing_tables = {
@ -165,16 +166,25 @@ class TestNBOVNBGPDriver(test_base.TestCase):
port1 = fakes.create_object({
'name': 'port-1',
'type': constants.OVN_CHASSISREDIRECT_VIF_PORT_TYPE})
lb1 = fakes.create_object({
'name': 'lb1',
'external_ids': {constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fake-fip'}
})
self.nb_idl.get_active_cr_lrp_on_chassis.return_value = [crlrp_port]
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
self.nb_idl.get_active_lsp_on_chassis.return_value = [
port0, port1]
self.nb_idl.get_active_local_lbs.return_value = [lb1]
mock_ensure_crlrp_exposed = mock.patch.object(
self.nb_bgp_driver, '_ensure_crlrp_exposed').start()
mock_expose_subnet = mock.patch.object(
self.nb_bgp_driver, '_expose_subnet').start()
mock_ensure_lsp_exposed = mock.patch.object(
self.nb_bgp_driver, '_ensure_lsp_exposed').start()
mock_expose_ovn_lb_vip = mock.patch.object(
self.nb_bgp_driver, '_expose_ovn_lb_vip').start()
mock_expose_ovn_lb_fip = mock.patch.object(
self.nb_bgp_driver, '_expose_ovn_lb_fip').start()
mock_routing_bridge.return_value = ['fake-route']
mock_nic_address.return_value = self.mac
mock_get_patch_ports.return_value = [1, 2]
@ -211,6 +221,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
'network': 'network1',
'address_scopes': {4: None, 6: None}})
mock_ensure_lsp_exposed.assert_called_once_with(port0)
mock_expose_ovn_lb_vip.assert_called_once_with(lb1)
mock_expose_ovn_lb_fip.assert_called_once_with(lb1)
mock_del_exposed_ips.assert_called_once_with(
ips, CONF.bgp_nic)
mock_del_ip_rules.assert_called_once_with(fake_ip_rules)
@ -443,13 +455,24 @@ class TestNBOVNBGPDriver(test_base.TestCase):
self.nb_bgp_driver.ovn_bridge_mappings = {'fake-localnet': 'br-ex'}
mock_expose_subnet = mock.patch.object(
self.nb_bgp_driver, '_expose_subnet').start()
lrp0 = fakes.create_object({
'name': 'lrp_port',
'external_ids': {
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
if (ips_info.get('router') and
ips_info['type'] == constants.OVN_CR_LRP_PORT_TYPE):
lrp0 = fakes.create_object({
'name': 'lrp_port',
'external_ids': {
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
lb1 = fakes.create_object({
'name': 'lb1', 'external_ids': {
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fake-fip'}})
self.nb_idl.get_active_local_lbs.return_value = [lb1]
mock_expose_ovn_lb_vip = mock.patch.object(
self.nb_bgp_driver, '_expose_ovn_lb_vip').start()
mock_expose_ovn_lb_fip = mock.patch.object(
self.nb_bgp_driver, '_expose_ovn_lb_fip').start()
self.nb_bgp_driver.expose_ip(ips, ips_info)
@ -480,6 +503,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
["10.0.0.1/24"], {'associated_router': 'router1',
'network': 'network1',
'address_scopes': {4: None, 6: None}})
mock_expose_ovn_lb_vip.assert_called_once_with(lb1)
mock_expose_ovn_lb_fip.assert_called_once_with(lb1)
def test_expose_ip(self):
ips = [self.ipv4, self.ipv6]
@ -542,13 +567,23 @@ class TestNBOVNBGPDriver(test_base.TestCase):
mock_withdraw_subnet = mock.patch.object(
self.nb_bgp_driver, '_withdraw_subnet').start()
lrp0 = fakes.create_object({
'name': 'lrp_port',
'external_ids': {
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
if (ips_info.get('router') and
ips_info['type'] == constants.OVN_CR_LRP_PORT_TYPE):
lrp0 = fakes.create_object({
'name': 'lrp_port',
'external_ids': {
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
lb1 = fakes.create_object({
'name': 'lb1', 'external_ids': {
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fake-fip'}})
self.nb_idl.get_active_local_lbs.return_value = [lb1]
mock_withdraw_ovn_lb_vip = mock.patch.object(
self.nb_bgp_driver, '_withdraw_ovn_lb_vip').start()
mock_withdraw_ovn_lb_fip = mock.patch.object(
self.nb_bgp_driver, '_withdraw_ovn_lb_fip').start()
self.nb_bgp_driver.withdraw_ip(ips, ips_info)
@ -578,6 +613,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
["10.0.0.1/24"], {'associated_router': 'router1',
'network': 'network1',
'address_scopes': {4: None, 6: None}})
mock_withdraw_ovn_lb_vip.assert_called_once_with(lb1)
mock_withdraw_ovn_lb_fip.assert_called_once_with(lb1)
def test_withdraw_ip(self):
ips = [self.ipv4, self.ipv6]
@ -1113,3 +1150,243 @@ class TestNBOVNBGPDriver(test_base.TestCase):
mock.ANY, ips[1], self.router1_info['bridge_device'],
self.router1_info['bridge_vlan'], mock.ANY,
self.router1_info['ips'])
def test_expose_ovn_lb_vip_tenant(self):
self.nb_bgp_driver.ovn_local_lrps = {'net1': ['ip1']}
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
vip_lsp = utils.create_row(
external_ids={
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'
})
self.nb_idl.lsp_get.return_value.execute.return_value = vip_lsp
mock_expose_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_expose_remote_ip').start()
mock_expose_provider_port = mock.patch.object(
self.nb_bgp_driver, '_expose_provider_port').start()
self.nb_bgp_driver.expose_ovn_lb_vip(lb)
mock_expose_remote_ip.assert_called_once_with(
['vip'], {'logical_switch': 'router1'}
)
mock_expose_provider_port.assert_not_called()
def test_expose_ovn_lb_vip_provider(self):
self.nb_bgp_driver.ovn_local_lrps = {'net1': ['ip1']}
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
vip_lsp = utils.create_row(
external_ids={
constants.OVN_LS_NAME_EXT_ID_KEY: 'net2'
})
self.nb_idl.lsp_get.return_value.execute.return_value = vip_lsp
mock_expose_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_expose_remote_ip').start()
mock_expose_provider_port = mock.patch.object(
self.nb_bgp_driver, '_expose_provider_port').start()
mock_get_ls_localnet_info = mock.patch.object(
self.nb_bgp_driver, '_get_ls_localnet_info').start()
mock_get_ls_localnet_info.return_value = (None, None, None)
self.nb_bgp_driver.expose_ovn_lb_vip(lb)
mock_expose_remote_ip.assert_not_called()
mock_get_ls_localnet_info.assert_called_once_with('net2')
mock_expose_provider_port.assert_called_once_with(
['vip'], None, 'net2', mock.ANY, mock.ANY, mock.ANY)
def test_expose_ovn_lb_vip_no_vip(self):
self.nb_bgp_driver.ovn_local_lrps = {'net1': ['ip1']}
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
self.nb_idl.lsp_get.return_value.execute.return_value = None
mock_expose_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_expose_remote_ip').start()
mock_expose_provider_port = mock.patch.object(
self.nb_bgp_driver, '_expose_provider_port').start()
self.nb_bgp_driver.expose_ovn_lb_vip(lb)
mock_expose_remote_ip.assert_not_called()
mock_expose_provider_port.assert_not_called()
def test_withdraw_ovn_lb_vip_tenant(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_withdraw_remote_ip').start()
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_vip(lb)
mock_withdraw_provider_port.assert_not_called()
mock_withdraw_remote_ip.assert_called_once_with(
['vip'], {'logical_switch': 'router1'})
def test_withdraw_ovn_lb_vip_provider(self):
self.nb_bgp_driver._exposed_ips = {
'provider-ls': {'vip': {'bridge_device': self.bridge,
'bridge_vlan': None}}}
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_withdraw_remote_ip').start()
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_vip(lb)
mock_withdraw_provider_port.assert_called_once_with(
['vip'],
self.router1_info['provider_switch'],
self.router1_info['bridge_device'],
self.router1_info['bridge_vlan'])
mock_withdraw_remote_ip.assert_not_called()
def test_withdraw_ovn_lb_vip_no_router(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_remote_ip = mock.patch.object(
self.nb_bgp_driver, '_withdraw_remote_ip').start()
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_vip(lb)
mock_withdraw_remote_ip.assert_not_called()
mock_withdraw_provider_port.assert_not_called()
def test_expose_ovn_lb_fip(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
vip_lsp = utils.create_row(
name='vip-port-name',
external_ids={
constants.OVN_LS_NAME_EXT_ID_KEY: 'net2'
})
self.nb_idl.lsp_get.return_value.execute.return_value = vip_lsp
mock_get_port_external_ip_and_ls = mock.patch.object(
self.nb_bgp_driver, 'get_port_external_ip_and_ls').start()
mock_get_port_external_ip_and_ls.return_value = ('fip',
'fip-mac',
'provider-ls')
mock_expose_fip = mock.patch.object(
self.nb_bgp_driver, '_expose_fip').start()
self.nb_bgp_driver.expose_ovn_lb_fip(lb)
mock_expose_fip.assert_called_once_with(
'fip', 'fip-mac', 'provider-ls', vip_lsp)
def test_expose_ovn_lb_fip_no_vip_port(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
self.nb_idl.lsp_get.return_value.execute.return_value = None
mock_expose_fip = mock.patch.object(
self.nb_bgp_driver, '_expose_fip').start()
self.nb_bgp_driver.expose_ovn_lb_fip(lb)
mock_expose_fip.assert_not_called()
def test_expose_ovn_lb_fip_no_external_ip(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip'},
vips={'vip': 'member', 'fip': 'member'})
vip_lsp = utils.create_row(
name='vip-port-name',
external_ids={
constants.OVN_LS_NAME_EXT_ID_KEY: 'net2'
})
self.nb_idl.lsp_get.return_value.execute.return_value = vip_lsp
mock_get_port_external_ip_and_ls = mock.patch.object(
self.nb_bgp_driver, 'get_port_external_ip_and_ls').start()
mock_get_port_external_ip_and_ls.return_value = (None, None, None)
mock_expose_fip = mock.patch.object(
self.nb_bgp_driver, '_expose_fip').start()
self.nb_bgp_driver.expose_ovn_lb_fip(lb)
mock_expose_fip.assert_not_called()
def test_withdraw_ovn_lb_fip(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'vip-fip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_fip(lb)
mock_withdraw_provider_port.assert_called_once_with(
['vip-fip'],
self.router1_info['provider_switch'],
self.router1_info['bridge_device'],
self.router1_info['bridge_vlan'])
def test_withdraw_ovn_lb_fip_no_vip_router(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'vip-fip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_fip(lb)
mock_withdraw_provider_port.assert_not_called()
def test_withdraw_ovn_lb_fip_no_cr_lrp(self):
lb = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2',
constants.OVN_LB_VIP_PORT_EXT_ID_KEY: 'vip_port',
constants.OVN_LB_VIP_IP_EXT_ID_KEY: 'vip',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'vip-fip'},
vips={'vip': 'member', 'fip': 'member'})
mock_withdraw_provider_port = mock.patch.object(
self.nb_bgp_driver, '_withdraw_provider_port').start()
self.nb_bgp_driver.withdraw_ovn_lb_fip(lb)
mock_withdraw_provider_port.assert_not_called()

View File

@ -203,6 +203,24 @@ class TestOvsdbNbOvnIdl(test_base.TestCase):
self.nb_idl.db_find_rows.assert_has_calls(expected_calls)
def test_get_active_local_lbs(self):
local_gateway_ports = ['router1']
lb1 = fakes.create_object({
'vips': {'vip': 'member1,member2'},
'external_ids': {
constants.OVN_LB_LR_REF_EXT_ID_KEY: "neutron-router1"}})
lb2 = fakes.create_object({
'vips': {'vip': 'member1,member2'},
'external_ids': {
constants.OVN_LB_LR_REF_EXT_ID_KEY: "neutron-router2"}})
self.nb_idl.db_find_rows.return_value.execute.return_value = [lb1, lb2]
ret = self.nb_idl.get_active_local_lbs(local_gateway_ports)
self.assertEqual([lb1], ret)
self.nb_idl.db_find_rows.assert_called_once_with(
'Load_Balancer', ('vips', '!=', {}))
class TestOvsdbSbOvnIdl(test_base.TestCase):

View File

@ -44,6 +44,33 @@ class TestPortBindingChassisEvent(test_base.TestCase):
'aa:bb:cc:dd:ee:ff 10.10.1.16 10.10.1.17 10.10.1.18'))
class FakeOVNLBEvent(base_watcher.OVNLBEvent):
def run(self):
pass
class TestOVNLBEvent(test_base.TestCase):
def setUp(self):
super(TestOVNLBEvent, self).setUp()
self.ovnlb_event = FakeOVNLBEvent(
mock.Mock(), [mock.Mock()])
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))
row = utils.create_row(external_ids={})
self.assertEqual(None, self.ovnlb_event._get_router(row))
def test__get_vip_fip(self):
row = utils.create_row(
external_ids={constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'})
self.assertEqual('fip', self.ovnlb_event._get_vip_fip(row))
row = utils.create_row(external_ids={})
self.assertEqual(None, self.ovnlb_event._get_vip_fip(row))
class FakeLSPChassisEvent(base_watcher.LSPChassisEvent):
def run(self):
pass

View File

@ -1098,3 +1098,291 @@ class TestLogicalSwitchPortTenantDeleteEvent(test_base.TestCase):
up=[True])
self.event.run(None, row, mock.Mock())
self.agent.withdraw_remote_ip.assert_not_called()
class TestOVNLBCreateEvent(test_base.TestCase):
def setUp(self):
super(TestOVNLBCreateEvent, self).setUp()
self.chassis = 'fake-chassis'
self.chassis_id = 'fake-chassis-id'
self.agent = mock.Mock(chassis=self.chassis,
chassis_id=self.chassis_id)
self.agent.ovn_local_cr_lrps = {
'router1': {'bridge_device': 'br-ex',
'bridge_vlan': None,
'ips': ['172.24.16.2']}}
self.event = nb_bgp_watcher.OVNLBCreateEvent(
self.agent)
def test_match_fn(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(vips={})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_router_added(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_fip_added(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_no_vips(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
self.assertFalse(self.event.match_fn(mock.Mock(), row, mock.Mock()))
def test_match_fn_no_local_crlrp(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
self.assertFalse(self.event.match_fn(mock.Mock(), row, mock.Mock()))
def test_run_vip(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(vips={})
self.event.run(None, row, old)
self.agent.expose_ovn_lb_vip.assert_called_once_with(row)
self.agent.expose_ovn_lb_fip.assert_not_called()
def test_run_vip_added_extra_ext_id_info(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1',
'other': 'info'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'})
self.event.run(None, row, old)
self.agent.expose_ovn_lb_vip.assert_not_called()
self.agent.expose_ovn_lb_fip.assert_not_called()
def test_run_fip(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'})
self.event.run(None, row, old)
self.agent.expose_ovn_lb_vip.assert_not_called()
self.agent.expose_ovn_lb_fip.assert_called_once_with(row)
class TestOVNLBDeleteEvent(test_base.TestCase):
def setUp(self):
super(TestOVNLBDeleteEvent, self).setUp()
self.chassis = 'fake-chassis'
self.chassis_id = 'fake-chassis-id'
self.agent = mock.Mock(chassis=self.chassis,
chassis_id=self.chassis_id)
self.agent.ovn_local_cr_lrps = {
'router1': {'bridge_device': 'br-ex',
'bridge_vlan': None,
'ips': ['172.24.16.2']}}
self.event = nb_bgp_watcher.OVNLBDeleteEvent(
self.agent)
def test_match_fn(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
old = utils.create_row(vips={'vip': 'member', 'fip': 'member'})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_delete(self):
event = self.event.ROW_DELETE
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
self.assertTrue(self.event.match_fn(event, row, mock.Mock()))
def test_match_fn_delete_no_vips(self):
event = self.event.ROW_DELETE
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
self.assertFalse(self.event.match_fn(event, row, mock.Mock()))
def test_match_fn_delete_no_local_router(self):
event = self.event.ROW_DELETE
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
self.assertFalse(self.event.match_fn(event, row, mock.Mock()))
def test_match_fn_router_deleted(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1'
})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_no_old_router(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={})
self.assertFalse(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_old_router_non_local(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router2',
})
self.assertFalse(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_fip_deleted(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_match_fn_vip_deleted_with_ext_id_update(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
old = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1',
'other': 'info'},
vips={'vip': 'member', 'fip': 'member'})
self.assertTrue(self.event.match_fn(mock.Mock(), row, old))
def test_run_vip(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
old = utils.create_row(vips={'vip': 'member'})
self.event.run(None, row, old)
self.agent.withdraw_ovn_lb_vip.assert_called_once_with(row)
self.agent.withdraw_ovn_lb_fip.assert_not_called()
def test_run_vip_delete(self):
event = self.event.ROW_DELETE
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={})
self.event.run(event, row, None)
self.agent.withdraw_ovn_lb_vip.assert_called_once_with(row)
self.agent.withdraw_ovn_lb_fip.assert_called_once_with(row)
def test_run_vip_deleted_extra_ext_id_info(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1',
'other': 'info'})
self.event.run(None, row, old)
self.agent.withdraw_ovn_lb_vip.assert_not_called()
self.agent.withdraw_ovn_lb_fip.assert_not_called()
def test_run_fip(self):
row = utils.create_row(
external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LS_NAME_EXT_ID_KEY: 'net1'},
vips={'vip': 'member', 'fip': 'member'})
old = utils.create_row(external_ids={
constants.OVN_LB_LR_REF_EXT_ID_KEY: 'neutron-router1',
constants.OVN_LB_VIP_FIP_EXT_ID_KEY: 'fip'})
self.event.run(None, row, old)
self.agent.withdraw_ovn_lb_vip.assert_not_called()
self.agent.withdraw_ovn_lb_fip.assert_called_once_with(old)