Add support at NB BGP Driver for exposing OVN LBs
Change-Id: I4b1992d938e157a693c9db33882e5bc27ef8f604
This commit is contained in:
parent
aaa0ae0c1a
commit
bb663ad778
@ -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``
|
The BGP watcher detects OVN Southbound Database events at the ``Port_Binding``
|
||||||
and ``Load_Balancer`` tables. It creates new event classes named
|
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).
|
watched for BGP use as the base (inherit from).
|
||||||
|
|
||||||
The specific defined events to react to are:
|
The specific defined events to react to are:
|
||||||
|
@ -79,7 +79,7 @@ networking accordingly.
|
|||||||
|
|
||||||
The BGP watcher detects OVN Southbound Database events at the ``Port_Binding``
|
The BGP watcher detects OVN Southbound Database events at the ``Port_Binding``
|
||||||
and ``Load_Balancer`` tables. It creates new event classes named
|
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).
|
watched for BGP use as the base (inherit from).
|
||||||
|
|
||||||
The driver react specifically to the following events:
|
The driver react specifically to the following events:
|
||||||
|
@ -33,6 +33,10 @@ OVN_DEVICE_OWNER_EXT_ID_KEY = 'neutron:device_owner'
|
|||||||
OVN_FIP_EXT_ID_KEY = 'neutron:port_fip'
|
OVN_FIP_EXT_ID_KEY = 'neutron:port_fip'
|
||||||
OVN_FIP_NET_EXT_ID_KEY = 'neutron:fip_network_id'
|
OVN_FIP_NET_EXT_ID_KEY = 'neutron:fip_network_id'
|
||||||
LB_VIP_PORT_PREFIX = "ovn-lb-vip-"
|
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_RULE_COOKIE = "999"
|
||||||
OVS_VRF_RULE_COOKIE = "998"
|
OVS_VRF_RULE_COOKIE = "998"
|
||||||
|
@ -36,7 +36,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
# logging.basicConfig(level=logging.DEBUG)
|
# logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
OVN_TABLES = ['Logical_Switch_Port', 'NAT', 'Logical_Switch',
|
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',
|
LOCAL_CLUSTER_OVN_TABLES = ['Logical_Switch', 'Logical_Switch_Port',
|
||||||
'Logical_Router', 'Logical_Router_Port',
|
'Logical_Router', 'Logical_Router_Port',
|
||||||
'Logical_Router_Policy',
|
'Logical_Router_Policy',
|
||||||
@ -146,7 +146,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
"LogicalSwitchPortProviderDeleteEvent",
|
"LogicalSwitchPortProviderDeleteEvent",
|
||||||
"LogicalSwitchPortFIPCreateEvent",
|
"LogicalSwitchPortFIPCreateEvent",
|
||||||
"LogicalSwitchPortFIPDeleteEvent",
|
"LogicalSwitchPortFIPDeleteEvent",
|
||||||
"LocalnetCreateDeleteEvent"])
|
"LocalnetCreateDeleteEvent",
|
||||||
|
"OVNLBCreateEvent",
|
||||||
|
"OVNLBDeleteEvent"])
|
||||||
if self._expose_tenant_networks:
|
if self._expose_tenant_networks:
|
||||||
events.update(["ChassisRedirectCreateEvent",
|
events.update(["ChassisRedirectCreateEvent",
|
||||||
"ChassisRedirectDeleteEvent",
|
"ChassisRedirectDeleteEvent",
|
||||||
@ -202,6 +204,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
continue
|
continue
|
||||||
self._ensure_lsp_exposed(port)
|
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
|
# remove extra wiring leftovers
|
||||||
wire_utils.cleanup_wiring(self.nb_idl,
|
wire_utils.cleanup_wiring(self.nb_idl,
|
||||||
self.ovn_bridge_mappings,
|
self.ovn_bridge_mappings,
|
||||||
@ -323,6 +328,22 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
bridge_vlan = localnet.tag[0]
|
bridge_vlan = localnet.tag[0]
|
||||||
return bridge_device, bridge_vlan
|
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')
|
@lockutils.synchronized('nbbgp')
|
||||||
def expose_ip(self, ips, ips_info):
|
def expose_ip(self, ips, ips_info):
|
||||||
'''Advertice BGP route by adding IP to device.
|
'''Advertice BGP route by adding IP to device.
|
||||||
@ -339,20 +360,28 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
logical_switch = ips_info.get('logical_switch')
|
logical_switch = ips_info.get('logical_switch')
|
||||||
if not logical_switch:
|
if not logical_switch:
|
||||||
return False
|
return False
|
||||||
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
|
|
||||||
logical_switch)
|
bridge_info = self.ovn_provider_ls.get(logical_switch)
|
||||||
if not bridge_device:
|
if bridge_info:
|
||||||
# This means it is not a provider network
|
# already known provider ls
|
||||||
self.ovn_tenant_ls[logical_switch] = True
|
bridge_device = bridge_info['bridge_device']
|
||||||
return False
|
bridge_vlan = bridge_info['bridge_vlan']
|
||||||
if bridge_device not in self.ovn_bridge_mappings.values():
|
localnet = bridge_info['localnet']
|
||||||
# This node is not properly configured, no need to expose it
|
else:
|
||||||
return False
|
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
|
||||||
if not self.ovn_provider_ls.get(logical_switch):
|
logical_switch)
|
||||||
self.ovn_provider_ls[logical_switch] = {
|
if not bridge_device:
|
||||||
'bridge_device': bridge_device,
|
# This means it is not a provider network
|
||||||
'bridge_vlan': bridge_vlan,
|
self.ovn_tenant_ls[logical_switch] = True
|
||||||
'localnet': localnet}
|
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')
|
mac = ips_info.get('mac')
|
||||||
return self._expose_ip(ips, mac, logical_switch, bridge_device,
|
return self._expose_ip(ips, mac, logical_switch, bridge_device,
|
||||||
bridge_vlan, port_type=ips_info['type'],
|
bridge_vlan, port_type=ips_info['type'],
|
||||||
@ -379,6 +408,7 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
self.ovn_local_cr_lrps[router] = {
|
self.ovn_local_cr_lrps[router] = {
|
||||||
'bridge_device': bridge_device,
|
'bridge_device': bridge_device,
|
||||||
'bridge_vlan': bridge_vlan,
|
'bridge_vlan': bridge_vlan,
|
||||||
|
'provider_switch': logical_switch,
|
||||||
'ips': ips,
|
'ips': ips,
|
||||||
}
|
}
|
||||||
# Expose associated subnets
|
# Expose associated subnets
|
||||||
@ -393,6 +423,9 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
constants.OVN_LS_NAME_EXT_ID_KEY),
|
constants.OVN_LS_NAME_EXT_ID_KEY),
|
||||||
'address_scopes': driver_utils.get_addr_scopes(port)}
|
'address_scopes': driver_utils.get_addr_scopes(port)}
|
||||||
self._expose_subnet(ips, subnet_info)
|
self._expose_subnet(ips, subnet_info)
|
||||||
|
|
||||||
|
# add missing routes/ips for OVN loadbalancers
|
||||||
|
self._expose_lbs([router])
|
||||||
else:
|
else:
|
||||||
if not self._expose_provider_port(ips, mac, logical_switch,
|
if not self._expose_provider_port(ips, mac, logical_switch,
|
||||||
bridge_device, bridge_vlan,
|
bridge_device, bridge_vlan,
|
||||||
@ -452,6 +485,10 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
constants.OVN_LS_NAME_EXT_ID_KEY),
|
constants.OVN_LS_NAME_EXT_ID_KEY),
|
||||||
'address_scopes': driver_utils.get_addr_scopes(port)}
|
'address_scopes': driver_utils.get_addr_scopes(port)}
|
||||||
self._withdraw_subnet(ips, subnet_info)
|
self._withdraw_subnet(ips, subnet_info)
|
||||||
|
|
||||||
|
# withdraw routes/ips for OVN loadbalancers
|
||||||
|
self._withdraw_lbs([ips_info['router']])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
del self.ovn_local_cr_lrps[ips_info['router']]
|
del self.ovn_local_cr_lrps[ips_info['router']]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -497,19 +534,26 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
return self._expose_fip(ip, mac, logical_switch, row)
|
return self._expose_fip(ip, mac, logical_switch, row)
|
||||||
|
|
||||||
def _expose_fip(self, ip, mac, logical_switch, row):
|
def _expose_fip(self, ip, mac, logical_switch, row):
|
||||||
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
|
bridge_info = self.ovn_provider_ls.get(logical_switch)
|
||||||
logical_switch)
|
if bridge_info:
|
||||||
if not bridge_device:
|
# already known provider ls
|
||||||
# This means it is not a provider network
|
bridge_device = bridge_info['bridge_device']
|
||||||
return False
|
bridge_vlan = bridge_info['bridge_vlan']
|
||||||
if bridge_device not in self.ovn_bridge_mappings.values():
|
localnet = bridge_info['localnet']
|
||||||
# This node is not properly configured, no need to expose it
|
else:
|
||||||
return False
|
localnet, bridge_device, bridge_vlan = self._get_ls_localnet_info(
|
||||||
if not self.ovn_provider_ls.get(logical_switch):
|
logical_switch)
|
||||||
self.ovn_provider_ls[logical_switch] = {
|
if not bridge_device:
|
||||||
'bridge_device': bridge_device,
|
# This means it is not a provider network
|
||||||
'bridge_vlan': bridge_vlan,
|
return False
|
||||||
'localnet': localnet}
|
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(
|
tenant_logical_switch = row.external_ids.get(
|
||||||
constants.OVN_LS_NAME_EXT_ID_KEY)
|
constants.OVN_LS_NAME_EXT_ID_KEY)
|
||||||
if not tenant_logical_switch:
|
if not tenant_logical_switch:
|
||||||
@ -556,6 +600,10 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
def expose_remote_ip(self, ips, ips_info):
|
def expose_remote_ip(self, ips, ips_info):
|
||||||
self._expose_remote_ip(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):
|
def _expose_remote_ip(self, ips, ips_info):
|
||||||
ips_to_expose = ips
|
ips_to_expose = ips
|
||||||
if not CONF.expose_tenant_networks:
|
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",
|
LOG.debug("Added BGP route for tenant IP(s) %s on chassis %s",
|
||||||
ips_to_expose, self.chassis)
|
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):
|
def _withdraw_remote_ip(self, ips, ips_info):
|
||||||
ips_to_withdraw = ips
|
ips_to_withdraw = ips
|
||||||
if not CONF.expose_tenant_networks:
|
if not CONF.expose_tenant_networks:
|
||||||
@ -737,6 +781,95 @@ class NBOVNBGPDriver(driver_api.AgentDriverBase):
|
|||||||
pass
|
pass
|
||||||
return True
|
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):
|
def _address_scope_allowed(self, ip, address_scopes):
|
||||||
if not self.allowed_address_scopes:
|
if not self.allowed_address_scopes:
|
||||||
# No address scopes to filter on => announce everything
|
# No address scopes to filter on => announce everything
|
||||||
|
@ -467,6 +467,16 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend):
|
|||||||
ports.extend(cmd.execute(check_error=True))
|
ports.extend(cmd.execute(check_error=True))
|
||||||
return ports
|
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
|
# FIXME(ltomasbo): This can be removed once ovsdbapp version is >=2.3.0
|
||||||
def ls_get_localnet_ports(self, logical_switch, if_exists=True):
|
def ls_get_localnet_ports(self, logical_switch, if_exists=True):
|
||||||
return LSGetLocalnetPortsCommand(self, logical_switch,
|
return LSGetLocalnetPortsCommand(self, logical_switch,
|
||||||
|
@ -42,14 +42,27 @@ class PortBindingChassisEvent(Event):
|
|||||||
return len(mac.strip().split(' ')) > 1
|
return len(mac.strip().split(' ')) > 1
|
||||||
|
|
||||||
|
|
||||||
class OVNLBMemberEvent(Event):
|
class OVNLBEvent(Event):
|
||||||
def __init__(self, bgp_agent, events):
|
def __init__(self, bgp_agent, events):
|
||||||
self.agent = bgp_agent
|
self.agent = bgp_agent
|
||||||
table = 'Load_Balancer'
|
table = 'Load_Balancer'
|
||||||
super(OVNLBMemberEvent, self).__init__(
|
super(OVNLBEvent, self).__init__(
|
||||||
events, table, None)
|
events, table, None)
|
||||||
self.event_name = self.__class__.__name__
|
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):
|
class LSPChassisEvent(Event):
|
||||||
def __init__(self, bgp_agent, events):
|
def __init__(self, bgp_agent, events):
|
||||||
@ -74,10 +87,10 @@ class LSPChassisEvent(Event):
|
|||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
def _get_network(self, row):
|
def _get_network(self, row):
|
||||||
if (hasattr(row, 'external_ids') and
|
try:
|
||||||
row.external_ids.get(constants.OVN_LS_NAME_EXT_ID_KEY)):
|
|
||||||
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
|
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
|
||||||
return None
|
except (AttributeError, KeyError):
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
class LRPChassisEvent(Event):
|
class LRPChassisEvent(Event):
|
||||||
@ -89,7 +102,7 @@ class LRPChassisEvent(Event):
|
|||||||
self.event_name = self.__class__.__name__
|
self.event_name = self.__class__.__name__
|
||||||
|
|
||||||
def _get_network(self, row):
|
def _get_network(self, row):
|
||||||
if (hasattr(row, 'external_ids') and
|
try:
|
||||||
row.external_ids.get(constants.OVN_LS_NAME_EXT_ID_KEY)):
|
|
||||||
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
|
return row.external_ids[constants.OVN_LS_NAME_EXT_ID_KEY]
|
||||||
return None
|
except (AttributeError, KeyError):
|
||||||
|
return
|
||||||
|
@ -372,7 +372,7 @@ class OVNLBVIPPortEvent(base_watcher.PortBindingChassisEvent):
|
|||||||
self.agent.expose_ovn_lb(ovn_lb_ip, row)
|
self.agent.expose_ovn_lb(ovn_lb_ip, row)
|
||||||
|
|
||||||
|
|
||||||
class OVNLBMemberCreateEvent(base_watcher.OVNLBMemberEvent):
|
class OVNLBMemberCreateEvent(base_watcher.OVNLBEvent):
|
||||||
def __init__(self, bgp_agent):
|
def __init__(self, bgp_agent):
|
||||||
events = (self.ROW_CREATE,)
|
events = (self.ROW_CREATE,)
|
||||||
super(OVNLBMemberCreateEvent, self).__init__(
|
super(OVNLBMemberCreateEvent, self).__init__(
|
||||||
@ -445,7 +445,7 @@ class OVNLBMemberCreateEvent(base_watcher.OVNLBMemberEvent):
|
|||||||
vip_ip, row.name, associated_cr_lrp_port)
|
vip_ip, row.name, associated_cr_lrp_port)
|
||||||
|
|
||||||
|
|
||||||
class OVNLBMemberDeleteEvent(base_watcher.OVNLBMemberEvent):
|
class OVNLBMemberDeleteEvent(base_watcher.OVNLBEvent):
|
||||||
def __init__(self, bgp_agent):
|
def __init__(self, bgp_agent):
|
||||||
events = (self.ROW_DELETE,)
|
events = (self.ROW_DELETE,)
|
||||||
super(OVNLBMemberDeleteEvent, self).__init__(
|
super(OVNLBMemberDeleteEvent, self).__init__(
|
||||||
|
@ -616,3 +616,122 @@ class LogicalSwitchPortTenantDeleteEvent(base_watcher.LSPChassisEvent):
|
|||||||
'logical_switch': self._get_network(row)
|
'logical_switch': self._get_network(row)
|
||||||
}
|
}
|
||||||
self.agent.withdraw_remote_ip(ips, ips_info)
|
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)
|
||||||
|
@ -59,7 +59,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
|||||||
|
|
||||||
self.router1_info = {'bridge_device': self.bridge,
|
self.router1_info = {'bridge_device': self.bridge,
|
||||||
'bridge_vlan': 100,
|
'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 = {
|
self.nb_bgp_driver.ovn_local_cr_lrps = {
|
||||||
'router1': self.router1_info}
|
'router1': self.router1_info}
|
||||||
self.ovn_routing_tables = {
|
self.ovn_routing_tables = {
|
||||||
@ -165,16 +166,25 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
|||||||
port1 = fakes.create_object({
|
port1 = fakes.create_object({
|
||||||
'name': 'port-1',
|
'name': 'port-1',
|
||||||
'type': constants.OVN_CHASSISREDIRECT_VIF_PORT_TYPE})
|
'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_cr_lrp_on_chassis.return_value = [crlrp_port]
|
||||||
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
|
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
|
||||||
self.nb_idl.get_active_lsp_on_chassis.return_value = [
|
self.nb_idl.get_active_lsp_on_chassis.return_value = [
|
||||||
port0, port1]
|
port0, port1]
|
||||||
|
self.nb_idl.get_active_local_lbs.return_value = [lb1]
|
||||||
mock_ensure_crlrp_exposed = mock.patch.object(
|
mock_ensure_crlrp_exposed = mock.patch.object(
|
||||||
self.nb_bgp_driver, '_ensure_crlrp_exposed').start()
|
self.nb_bgp_driver, '_ensure_crlrp_exposed').start()
|
||||||
mock_expose_subnet = mock.patch.object(
|
mock_expose_subnet = mock.patch.object(
|
||||||
self.nb_bgp_driver, '_expose_subnet').start()
|
self.nb_bgp_driver, '_expose_subnet').start()
|
||||||
mock_ensure_lsp_exposed = mock.patch.object(
|
mock_ensure_lsp_exposed = mock.patch.object(
|
||||||
self.nb_bgp_driver, '_ensure_lsp_exposed').start()
|
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_routing_bridge.return_value = ['fake-route']
|
||||||
mock_nic_address.return_value = self.mac
|
mock_nic_address.return_value = self.mac
|
||||||
mock_get_patch_ports.return_value = [1, 2]
|
mock_get_patch_ports.return_value = [1, 2]
|
||||||
@ -211,6 +221,8 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
|||||||
'network': 'network1',
|
'network': 'network1',
|
||||||
'address_scopes': {4: None, 6: None}})
|
'address_scopes': {4: None, 6: None}})
|
||||||
mock_ensure_lsp_exposed.assert_called_once_with(port0)
|
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(
|
mock_del_exposed_ips.assert_called_once_with(
|
||||||
ips, CONF.bgp_nic)
|
ips, CONF.bgp_nic)
|
||||||
mock_del_ip_rules.assert_called_once_with(fake_ip_rules)
|
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'}
|
self.nb_bgp_driver.ovn_bridge_mappings = {'fake-localnet': 'br-ex'}
|
||||||
mock_expose_subnet = mock.patch.object(
|
mock_expose_subnet = mock.patch.object(
|
||||||
self.nb_bgp_driver, '_expose_subnet').start()
|
self.nb_bgp_driver, '_expose_subnet').start()
|
||||||
lrp0 = fakes.create_object({
|
|
||||||
'name': 'lrp_port',
|
if (ips_info.get('router') and
|
||||||
'external_ids': {
|
ips_info['type'] == constants.OVN_CR_LRP_PORT_TYPE):
|
||||||
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
|
lrp0 = fakes.create_object({
|
||||||
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
|
'name': 'lrp_port',
|
||||||
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
|
'external_ids': {
|
||||||
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
|
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)
|
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',
|
["10.0.0.1/24"], {'associated_router': 'router1',
|
||||||
'network': 'network1',
|
'network': 'network1',
|
||||||
'address_scopes': {4: None, 6: None}})
|
'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):
|
def test_expose_ip(self):
|
||||||
ips = [self.ipv4, self.ipv6]
|
ips = [self.ipv4, self.ipv6]
|
||||||
@ -542,13 +567,23 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
|||||||
|
|
||||||
mock_withdraw_subnet = mock.patch.object(
|
mock_withdraw_subnet = mock.patch.object(
|
||||||
self.nb_bgp_driver, '_withdraw_subnet').start()
|
self.nb_bgp_driver, '_withdraw_subnet').start()
|
||||||
lrp0 = fakes.create_object({
|
if (ips_info.get('router') and
|
||||||
'name': 'lrp_port',
|
ips_info['type'] == constants.OVN_CR_LRP_PORT_TYPE):
|
||||||
'external_ids': {
|
lrp0 = fakes.create_object({
|
||||||
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
|
'name': 'lrp_port',
|
||||||
constants.OVN_LS_NAME_EXT_ID_KEY: 'network1',
|
'external_ids': {
|
||||||
constants.OVN_DEVICE_ID_EXT_ID_KEY: 'router1'}})
|
constants.OVN_CIDRS_EXT_ID_KEY: "10.0.0.1/24",
|
||||||
self.nb_idl.get_active_local_lrps.return_value = [lrp0]
|
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)
|
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',
|
["10.0.0.1/24"], {'associated_router': 'router1',
|
||||||
'network': 'network1',
|
'network': 'network1',
|
||||||
'address_scopes': {4: None, 6: None}})
|
'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):
|
def test_withdraw_ip(self):
|
||||||
ips = [self.ipv4, self.ipv6]
|
ips = [self.ipv4, self.ipv6]
|
||||||
@ -1113,3 +1150,243 @@ class TestNBOVNBGPDriver(test_base.TestCase):
|
|||||||
mock.ANY, ips[1], self.router1_info['bridge_device'],
|
mock.ANY, ips[1], self.router1_info['bridge_device'],
|
||||||
self.router1_info['bridge_vlan'], mock.ANY,
|
self.router1_info['bridge_vlan'], mock.ANY,
|
||||||
self.router1_info['ips'])
|
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()
|
||||||
|
@ -203,6 +203,24 @@ class TestOvsdbNbOvnIdl(test_base.TestCase):
|
|||||||
|
|
||||||
self.nb_idl.db_find_rows.assert_has_calls(expected_calls)
|
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):
|
class TestOvsdbSbOvnIdl(test_base.TestCase):
|
||||||
|
|
||||||
|
@ -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'))
|
'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):
|
class FakeLSPChassisEvent(base_watcher.LSPChassisEvent):
|
||||||
def run(self):
|
def run(self):
|
||||||
pass
|
pass
|
||||||
|
@ -1098,3 +1098,291 @@ class TestLogicalSwitchPortTenantDeleteEvent(test_base.TestCase):
|
|||||||
up=[True])
|
up=[True])
|
||||||
self.event.run(None, row, mock.Mock())
|
self.event.run(None, row, mock.Mock())
|
||||||
self.agent.withdraw_remote_ip.assert_not_called()
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user