Merge "[OVN] A LRP in an external tunnelled network has no chassis"
This commit is contained in:
commit
a8fe0cb369
@ -1531,11 +1531,13 @@ class OVNClient(object):
|
||||
"""Return chassis for scheduling gateway router.
|
||||
|
||||
Criteria for selecting chassis as candidates
|
||||
1) chassis from cms with proper bridge mappings
|
||||
2) if no chassis is available from 1) then,
|
||||
select chassis with proper bridge mappings
|
||||
3) Filter the available chassis accordingly to the routers
|
||||
1) Chassis from cms with proper bridge mappings only (that means these
|
||||
gateway chassis with the requested physical network).
|
||||
2) Filter the available chassis accordingly to the routers
|
||||
availability zone hints (if present)
|
||||
|
||||
If the logical router port belongs to a tunnelled network, there won't
|
||||
be any candidate.
|
||||
"""
|
||||
# TODO(lucasagomes): Simplify the logic here, the CMS option has
|
||||
# been introduced long ago and by now all gateway chassis should
|
||||
@ -1544,15 +1546,13 @@ class OVNClient(object):
|
||||
cms = cms or self._sb_idl.get_gateway_chassis_from_cms_options()
|
||||
chassis_physnets = (chassis_physnets or
|
||||
self._sb_idl.get_chassis_and_physnets())
|
||||
cms_bmaps = []
|
||||
bmaps = []
|
||||
candidates = set()
|
||||
for chassis, physnets in chassis_physnets.items():
|
||||
if physnet and physnet in physnets:
|
||||
if chassis in cms:
|
||||
cms_bmaps.append(chassis)
|
||||
else:
|
||||
bmaps.append(chassis)
|
||||
candidates = cms_bmaps or bmaps or cms
|
||||
if (physnet and
|
||||
physnet in physnets and
|
||||
chassis in cms):
|
||||
candidates.add(chassis)
|
||||
candidates = list(candidates)
|
||||
|
||||
# Filter for availability zones
|
||||
if availability_zone_hints:
|
||||
@ -1563,11 +1563,8 @@ class OVNClient(object):
|
||||
if az in utils.get_chassis_availability_zones(
|
||||
self._sb_idl.lookup('Chassis', ch, None))]
|
||||
|
||||
if not cms_bmaps:
|
||||
LOG.debug("No eligible chassis with external connectivity"
|
||||
" through ovn-cms-options for %s", physnet)
|
||||
LOG.debug("Chassis candidates for scheduling gateway router ports: %s",
|
||||
candidates)
|
||||
LOG.debug('Chassis candidates for scheduling gateway router ports '
|
||||
'for "%s" physical network: %s', physnet, candidates)
|
||||
return candidates
|
||||
|
||||
def _get_physnet(self, network):
|
||||
|
@ -33,12 +33,14 @@ from neutron.tests.functional.resources.ovsdb import events
|
||||
|
||||
|
||||
class TestRouter(base.TestOVNFunctionalBase):
|
||||
def setUp(self):
|
||||
super(TestRouter, self).setUp()
|
||||
def setUp(self, **kwargs):
|
||||
super().setUp(**kwargs)
|
||||
self.chassis1 = self.add_fake_chassis(
|
||||
'ovs-host1', physical_nets=['physnet1', 'physnet3'])
|
||||
'ovs-host1', physical_nets=['physnet1', 'physnet3'],
|
||||
enable_chassis_as_gw=True, azs=[])
|
||||
self.chassis2 = self.add_fake_chassis(
|
||||
'ovs-host2', physical_nets=['physnet2', 'physnet3'])
|
||||
'ovs-host2', physical_nets=['physnet2', 'physnet3'],
|
||||
enable_chassis_as_gw=True, azs=[])
|
||||
self.cr_lrp_pb_event = events.WaitForCrLrpPortBindingEvent()
|
||||
self.sb_api.idl.notify_handler.watch_event(self.cr_lrp_pb_event)
|
||||
|
||||
@ -105,12 +107,14 @@ class TestRouter(base.TestOVNFunctionalBase):
|
||||
self.assertCountEqual(expected, chassis)
|
||||
|
||||
def _check_gateway_chassis_candidates(self, candidates,
|
||||
router_az_hints=None):
|
||||
router_az_hints=None,
|
||||
physnet='physnet1'):
|
||||
# In this test, fake_select() is called once from _create_router()
|
||||
# and later from schedule_unhosted_gateways()
|
||||
ovn_client = self.l3_plugin._ovn_client
|
||||
net_type = 'vlan' if physnet else 'geneve'
|
||||
ext1 = self._create_ext_network(
|
||||
'ext1', 'vlan', 'physnet1', 1, "10.0.0.1", "10.0.0.0/24")
|
||||
'ext1', net_type, physnet, 1, "10.0.0.1", "10.0.0.0/24")
|
||||
# mock select function and check if it is called with expected
|
||||
# candidates.
|
||||
|
||||
@ -141,12 +145,11 @@ class TestRouter(base.TestOVNFunctionalBase):
|
||||
|
||||
def test_gateway_chassis_with_cms_and_bridge_mappings(self):
|
||||
# Both chassis1 and chassis3 are having proper bridge mappings,
|
||||
# but only chassis3 is having enable-chassis-as-gw.
|
||||
# Test if chassis3 is selected as candidate or not.
|
||||
# but only chassis1 is having enable-chassis-as-gw.
|
||||
# Test if chassis1 is selected as candidate or not.
|
||||
self.chassis3 = self.add_fake_chassis(
|
||||
'ovs-host3', physical_nets=['physnet1'],
|
||||
other_config={'ovn-cms-options': 'enable-chassis-as-gw'})
|
||||
self._check_gateway_chassis_candidates([self.chassis3])
|
||||
'ovs-host3', physical_nets=['physnet1'], azs=[])
|
||||
self._check_gateway_chassis_candidates([self.chassis1])
|
||||
|
||||
def test_gateway_chassis_with_cms_and_no_bridge_mappings(self):
|
||||
# chassis1 is having proper bridge mappings.
|
||||
@ -180,12 +183,10 @@ class TestRouter(base.TestOVNFunctionalBase):
|
||||
# Test if chassis3 is selected as candidate or not.
|
||||
self.chassis3 = self.add_fake_chassis(
|
||||
'ovs-host3', physical_nets=['physnet1'],
|
||||
other_config={'ovn-cms-options': 'enable-chassis-as-gw'},
|
||||
azs=['ovn'])
|
||||
azs=['ovn'], enable_chassis_as_gw=True)
|
||||
self.chassis4 = self.add_fake_chassis(
|
||||
'ovs-host4', physical_nets=['physnet1'],
|
||||
other_config={'ovn-cms-options': 'enable-chassis-as-gw'},
|
||||
azs=['ovn2'])
|
||||
azs=['ovn2'], enable_chassis_as_gw=True)
|
||||
self._check_gateway_chassis_candidates([self.chassis3],
|
||||
router_az_hints=['ovn'])
|
||||
|
||||
@ -195,11 +196,9 @@ class TestRouter(base.TestOVNFunctionalBase):
|
||||
# AvailabilityZoneNotFound. after create will delete if.
|
||||
# add chassis4 is having azs [ovn2], not match routers az_hints [ovn]
|
||||
self.chassis3 = self.add_fake_chassis(
|
||||
'ovs-host3', physical_nets=['physnet1'],
|
||||
other_config={'ovn-cms-options': 'enable-chassis-as-gw'})
|
||||
'ovs-host3', physical_nets=['physnet1'], enable_chassis_as_gw=True)
|
||||
self.chassis4 = self.add_fake_chassis(
|
||||
'ovs-host4', physical_nets=['physnet1'],
|
||||
other_config={'ovn-cms-options': 'enable-chassis-as-gw'},
|
||||
'ovs-host4', physical_nets=['physnet1'], enable_chassis_as_gw=True,
|
||||
azs=['ovn2'])
|
||||
ovn_client = self.l3_plugin._ovn_client
|
||||
ext1 = self._create_ext_network(
|
||||
@ -227,6 +226,11 @@ class TestRouter(base.TestOVNFunctionalBase):
|
||||
# Test if chassis1 is selected as candidate or not.
|
||||
self._check_gateway_chassis_candidates([self.chassis1])
|
||||
|
||||
def test_gateway_chassis_no_physnet_tunnelled_network(self):
|
||||
# The GW network is tunnelled, no physnet defined --> no possible
|
||||
# candidates.
|
||||
self._check_gateway_chassis_candidates([], physnet=None)
|
||||
|
||||
def test_gateway_chassis_least_loaded_scheduler(self):
|
||||
# This test will create 4 routers each with its own gateway.
|
||||
# Using the least loaded policy for scheduling gateway ports, we
|
||||
|
@ -2643,24 +2643,27 @@ class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
||||
return ch
|
||||
ovn_client._sb_idl.lookup = fake_lookup
|
||||
|
||||
# The target physnet and availability zones
|
||||
physnet = 'public'
|
||||
az_hints = ['az0', 'az2']
|
||||
|
||||
# List of chassis and chassis:physnet mappings.
|
||||
physnet_name = 'public'
|
||||
cms = [ch0.name, ch1.name, ch2.name, ch3.name, ch4.name, ch5.name]
|
||||
ch_physnet = {ch0.name: [physnet], ch1.name: [physnet],
|
||||
ch2.name: [physnet], ch3.name: [physnet],
|
||||
ch_physnet = {ch0.name: [physnet_name], ch1.name: [physnet_name],
|
||||
ch2.name: [physnet_name], ch3.name: [physnet_name],
|
||||
ch4.name: ['another-physnet'],
|
||||
ch5.name: ['yet-another-physnet']}
|
||||
|
||||
candidates = ovn_client.get_candidates_for_scheduling(
|
||||
physnet, cms=cms, chassis_physnets=ch_physnet,
|
||||
availability_zone_hints=az_hints)
|
||||
|
||||
# Only chassis ch0 and ch2 should match the availability zones
|
||||
# hints and physnet we passed to get_candidates_for_scheduling()
|
||||
expected_candidates = [ch0.name, ch2.name]
|
||||
self.assertEqual(sorted(expected_candidates), sorted(candidates))
|
||||
# The target physnets, the availability zones and the expected
|
||||
# candidates.
|
||||
results = [{'physnet': physnet_name, 'az_hints': ['az0', 'az2'],
|
||||
'expected_candidates': [ch0.name, ch2.name]},
|
||||
{'physnet': None, 'az_hints': ['az0', 'az2'],
|
||||
'expected_candidates': []},
|
||||
]
|
||||
for result in results:
|
||||
candidates = ovn_client.get_candidates_for_scheduling(
|
||||
result['physnet'], cms=cms, chassis_physnets=ch_physnet,
|
||||
availability_zone_hints=result['az_hints'])
|
||||
self.assertEqual(sorted(result['expected_candidates']),
|
||||
sorted(candidates))
|
||||
|
||||
def test__get_info_for_ha_chassis_group_as_extport(self):
|
||||
net_attrs = {az_def.AZ_HINTS: ['az0', 'az1', 'az2']}
|
||||
|
Loading…
Reference in New Issue
Block a user