Skip to content

Commit 9d7b36d

Browse files
authored
Merge pull request #135 from stackhpc/upstream/2023.1-2024-04-01
Synchronise 2023.1 with upstream
2 parents 29cf022 + ee607d8 commit 9d7b36d

File tree

11 files changed

+95
-50
lines changed

11 files changed

+95
-50
lines changed

neutron/agent/linux/iptables_firewall.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -599,9 +599,15 @@ def _select_sg_rules_for_port(self, port, direction):
599599
rule, port, direction))
600600
return port_rules
601601

602+
def _get_any_remote_group_id_in_rule(self, rule):
603+
remote_group_id = rule.get('remote_group_id')
604+
if not remote_group_id:
605+
remote_group_id = rule.get('remote_address_group_id')
606+
return remote_group_id
607+
602608
def _expand_sg_rule_with_remote_ips(self, rule, port, direction):
603609
"""Expand a remote group rule to rule per remote group IP."""
604-
remote_group_id = rule.get('remote_group_id')
610+
remote_group_id = self._get_any_remote_group_id_in_rule(rule)
605611
if remote_group_id:
606612
ethertype = rule['ethertype']
607613
port_ips = port.get('fixed_ips', [])
@@ -623,7 +629,7 @@ def _get_remote_sg_ids(self, port, direction=None):
623629
for sg_id in sg_ids:
624630
for rule in self.sg_rules.get(sg_id, []):
625631
if not direction or rule['direction'] == direction:
626-
remote_sg_id = rule.get('remote_group_id')
632+
remote_sg_id = self._get_any_remote_group_id_in_rule(rule)
627633
ether_type = rule.get('ethertype')
628634
if remote_sg_id and ether_type:
629635
remote_sg_ids[ether_type].add(remote_sg_id)
@@ -703,7 +709,7 @@ def _generate_plain_rule_args(self, sg_rule):
703709
return args
704710

705711
def _convert_sg_rule_to_iptables_args(self, sg_rule):
706-
remote_gid = sg_rule.get('remote_group_id')
712+
remote_gid = self._get_any_remote_group_id_in_rule(sg_rule)
707713
if self.enable_ipset and remote_gid:
708714
return self._generate_ipset_rule_args(sg_rule, remote_gid)
709715
else:

neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/maintenance.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -978,8 +978,10 @@ def add_gw_port_info_to_logical_router_port(self):
978978
cmds = []
979979
context = n_context.get_admin_context()
980980
for router in self._ovn_client._l3_plugin.get_routers(context):
981-
ext_gw_networks = [
982-
ext_gw['network_id'] for ext_gw in router['external_gateways']]
981+
ext_gw_net_id = (router.get('external_gateway_info') or
982+
{}).get('network_id')
983+
if not ext_gw_net_id:
984+
continue
983985
rtr_name = 'neutron-{}'.format(router['id'])
984986
ovn_lr = self._nb_idl.get_lrouter(rtr_name)
985987
for lrp in ovn_lr.ports:
@@ -992,7 +994,7 @@ def add_gw_port_info_to_logical_router_port(self):
992994
network_id = ovn_network_name.replace('neutron-', '')
993995
if not network_id:
994996
continue
995-
is_ext_gw = str(network_id in ext_gw_networks)
997+
is_ext_gw = str(network_id == ext_gw_net_id)
996998
external_ids = lrp.external_ids
997999
external_ids[ovn_const.OVN_ROUTER_IS_EXT_GW] = is_ext_gw
9981000
cmds.append(

neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/ovn_client.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,8 +1651,7 @@ def _create_lrouter_port(self, context, router, port, txn=None):
16511651
physnet, availability_zone_hints=common_utils.get_az_hints(
16521652
router))
16531653
selected_chassis = self._ovn_scheduler.select(
1654-
self._nb_idl, self._sb_idl, lrouter_port_name,
1655-
candidates=candidates)
1654+
self._nb_idl, lrouter_port_name, candidates=candidates)
16561655
if selected_chassis:
16571656
columns['gateway_chassis'] = selected_chassis
16581657

neutron/scheduler/l3_ovn_scheduler.py

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def __init__(self):
3535
pass
3636

3737
@abc.abstractmethod
38-
def select(self, nb_idl, sb_idl, gateway_name, candidates=None):
38+
def select(self, nb_idl, gateway_name, candidates=None):
3939
"""Schedule the gateway port of a router to an OVN chassis.
4040
4141
Schedule the gateway router port only if it is not already
@@ -57,10 +57,10 @@ def filter_existing_chassis(self, nb_idl, gw_chassis,
5757
chassis_list.remove(chassis_name)
5858
return chassis_list
5959

60-
def _schedule_gateway(self, nb_idl, sb_idl, gateway_name, candidates,
60+
def _schedule_gateway(self, nb_idl, gateway_name, candidates,
6161
existing_chassis):
6262
existing_chassis = existing_chassis or []
63-
candidates = candidates or self._get_chassis_candidates(sb_idl)
63+
candidates = candidates or []
6464
candidates = list(set(candidates) - set(existing_chassis))
6565
# If no candidates, or gateway scheduled on MAX_GATEWAY_CHASSIS nodes
6666
# or all candidates in existing_chassis, return existing_chassis.
@@ -70,6 +70,8 @@ def _schedule_gateway(self, nb_idl, sb_idl, gateway_name, candidates,
7070
len(existing_chassis) == ovn_const.MAX_GW_CHASSIS):
7171
return existing_chassis
7272
if not candidates:
73+
LOG.warning('Gateway %s was not scheduled on any chassis, no '
74+
'candidates are available', gateway_name)
7375
return [ovn_const.OVN_GATEWAY_INVALID_CHASSIS]
7476
chassis_count = ovn_const.MAX_GW_CHASSIS - len(existing_chassis)
7577
# The actual binding of the gateway to a chassis via the options
@@ -88,20 +90,13 @@ def _schedule_gateway(self, nb_idl, sb_idl, gateway_name, candidates,
8890
def _select_gateway_chassis(self, nb_idl, candidates):
8991
"""Choose a chassis from candidates based on a specific policy."""
9092

91-
def _get_chassis_candidates(self, sb_idl):
92-
# TODO(azbiswas): Allow selection of a specific type of chassis when
93-
# the upstream code merges.
94-
# return (sb_idl.get_all_chassis('gateway_router') or
95-
# sb_idl.get_all_chassis())
96-
return sb_idl.get_all_chassis()
97-
9893

9994
class OVNGatewayChanceScheduler(OVNGatewayScheduler):
10095
"""Randomly select an chassis for a gateway port of a router"""
10196

102-
def select(self, nb_idl, sb_idl, gateway_name, candidates=None,
97+
def select(self, nb_idl, gateway_name, candidates=None,
10398
existing_chassis=None):
104-
return self._schedule_gateway(nb_idl, sb_idl, gateway_name,
99+
return self._schedule_gateway(nb_idl, gateway_name,
105100
candidates, existing_chassis)
106101

107102
def _select_gateway_chassis(self, nb_idl, candidates):
@@ -113,9 +108,9 @@ def _select_gateway_chassis(self, nb_idl, candidates):
113108
class OVNGatewayLeastLoadedScheduler(OVNGatewayScheduler):
114109
"""Select the least loaded chassis for a gateway port of a router"""
115110

116-
def select(self, nb_idl, sb_idl, gateway_name, candidates=None,
111+
def select(self, nb_idl, gateway_name, candidates=None,
117112
existing_chassis=None):
118-
return self._schedule_gateway(nb_idl, sb_idl, gateway_name,
113+
return self._schedule_gateway(nb_idl, gateway_name,
119114
candidates, existing_chassis)
120115

121116
@staticmethod

neutron/services/ovn_l3/plugin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ def schedule_unhosted_gateways(self, event_from_chassis=None):
434434
chassis_physnets=chassis_with_physnets,
435435
availability_zone_hints=az_hints)
436436
chassis = self.scheduler.select(
437-
self._nb_ovn, self._sb_ovn, g_name, candidates=candidates,
437+
self._nb_ovn, g_name, candidates=candidates,
438438
existing_chassis=existing_chassis)
439439
if primary and primary != chassis[0]:
440440
if primary not in chassis:

neutron/tests/unit/agent/linux/test_iptables_firewall.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,6 +2333,22 @@ def test_filter_defer_apply_off_with_sg_only_ipv6_rule(self):
23332333

23342334
self.firewall.ipset.assert_has_calls(calls, True)
23352335

2336+
def test__get_any_remote_group_id_in_rule_with_remote_group(self):
2337+
sg_rule = {'direction': 'ingress',
2338+
'remote_group_id': FAKE_SGID,
2339+
'ethertype': _IPv4}
2340+
2341+
self.assertEqual(FAKE_SGID,
2342+
self.firewall._get_any_remote_group_id_in_rule(sg_rule))
2343+
2344+
def test__get_any_remote_group_id_in_rule_with_remote_address_group(self):
2345+
sg_rule = {'direction': 'ingress',
2346+
'remote_address_group_id': FAKE_SGID,
2347+
'ethertype': _IPv6}
2348+
2349+
self.assertEqual(FAKE_SGID,
2350+
self.firewall._get_any_remote_group_id_in_rule(sg_rule))
2351+
23362352
def test_sg_rule_expansion_with_remote_ips(self):
23372353
other_ips = [('10.0.0.2', 'fa:16:3e:aa:bb:c1'),
23382354
('10.0.0.3', 'fa:16:3e:aa:bb:c2'),

neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_maintenance.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,7 @@ def test_add_gw_port_info_to_logical_router_port(self):
943943
internal_net_id = uuidutils.generate_uuid()
944944
routers_db = [{
945945
'id': uuidutils.generate_uuid(),
946-
'external_gateways': [{'network_id': ext_net_id}]}]
946+
'external_gateway_info': {'network_id': ext_net_id}}]
947947
ext_gw_lrp = fakes.FakeOvsdbRow.create_one_ovsdb_row(
948948
attrs={'external_ids': {
949949
constants.OVN_NETWORK_NAME_EXT_ID_KEY:

neutron/tests/unit/scheduler/test_l3_ovn_scheduler.py

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,11 @@ def __init__(self, chassis_gateway_mapping, gateway):
3030
None))
3131

3232

33-
class FakeOVNGatewaySchedulerSbOvnIdl(object):
34-
def __init__(self, chassis_gateway_mapping):
35-
self.get_all_chassis = mock.Mock(
36-
return_value=chassis_gateway_mapping['Chassis'])
37-
38-
3933
class TestOVNGatewayScheduler(base.BaseTestCase):
4034

4135
def setUp(self):
4236
super(TestOVNGatewayScheduler, self).setUp()
37+
self.mock_log = mock.patch.object(l3_ovn_scheduler, 'LOG').start()
4338

4439
# Overwritten by derived classes
4540
self.l3_scheduler = None
@@ -82,12 +77,11 @@ def setUp(self):
8277
if chassis in details['Chassis_Bindings']:
8378
details['Chassis_Bindings'][chassis].append((gw, 0))
8479

85-
def select(self, chassis_gateway_mapping, gateway_name):
80+
def select(self, chassis_gateway_mapping, gateway_name, candidates=None):
8681
nb_idl = FakeOVNGatewaySchedulerNbOvnIdl(chassis_gateway_mapping,
8782
gateway_name)
88-
sb_idl = FakeOVNGatewaySchedulerSbOvnIdl(chassis_gateway_mapping)
89-
return self.l3_scheduler.select(nb_idl, sb_idl,
90-
gateway_name)
83+
return self.l3_scheduler.select(nb_idl, gateway_name,
84+
candidates=candidates)
9185

9286
def filter_existing_chassis(self, *args, **kwargs):
9387
return self.l3_scheduler.filter_existing_chassis(
@@ -108,21 +102,33 @@ def setUp(self):
108102
def test_no_chassis_available_for_existing_gateway(self):
109103
mapping = self.fake_chassis_gateway_mappings['None']
110104
gateway_name = random.choice(list(mapping['Gateways'].keys()))
111-
chassis = self.select(mapping, gateway_name)
105+
chassis = self.select(mapping, gateway_name,
106+
candidates=mapping['Chassis'])
112107
self.assertEqual([ovn_const.OVN_GATEWAY_INVALID_CHASSIS], chassis)
113108

114109
def test_no_chassis_available_for_new_gateway(self):
115110
mapping = self.fake_chassis_gateway_mappings['None']
116111
gateway_name = self.new_gateway_name
117-
chassis = self.select(mapping, gateway_name)
112+
chassis = self.select(mapping, gateway_name,
113+
candidates=mapping['Chassis'])
118114
self.assertEqual([ovn_const.OVN_GATEWAY_INVALID_CHASSIS], chassis)
119115

120116
def test_random_chassis_available_for_new_gateway(self):
121117
mapping = self.fake_chassis_gateway_mappings['Multiple1']
122118
gateway_name = self.new_gateway_name
123-
chassis = self.select(mapping, gateway_name)
119+
chassis = self.select(mapping, gateway_name,
120+
candidates=mapping['Chassis'])
124121
self.assertCountEqual(chassis, mapping.get('Chassis'))
125122

123+
def test_no_candidates_provided(self):
124+
mapping = self.fake_chassis_gateway_mappings['None']
125+
gateway_name = self.new_gateway_name
126+
chassis = self.select(mapping, gateway_name)
127+
self.assertEqual([ovn_const.OVN_GATEWAY_INVALID_CHASSIS], chassis)
128+
self.mock_log.warning.assert_called_once_with(
129+
'Gateway %s was not scheduled on any chassis, no candidates are '
130+
'available', gateway_name)
131+
126132
def test_filter_existing_chassis(self):
127133
# filter_existing_chassis is scheduler independent, but calling
128134
# it from Base class didnt seem right. Also, there is no need to have
@@ -171,19 +177,22 @@ def setUp(self):
171177
def test_no_chassis_available_for_existing_gateway(self):
172178
mapping = self.fake_chassis_gateway_mappings['None']
173179
gateway_name = random.choice(list(mapping['Gateways'].keys()))
174-
chassis = self.select(mapping, gateway_name)
180+
chassis = self.select(mapping, gateway_name,
181+
candidates=mapping['Chassis'])
175182
self.assertEqual([ovn_const.OVN_GATEWAY_INVALID_CHASSIS], chassis)
176183

177184
def test_no_chassis_available_for_new_gateway(self):
178185
mapping = self.fake_chassis_gateway_mappings['None']
179186
gateway_name = self.new_gateway_name
180-
chassis = self.select(mapping, gateway_name)
187+
chassis = self.select(mapping, gateway_name,
188+
candidates=mapping['Chassis'])
181189
self.assertEqual([ovn_const.OVN_GATEWAY_INVALID_CHASSIS], chassis)
182190

183191
def test_least_loaded_chassis_available_for_new_gateway1(self):
184192
mapping = self.fake_chassis_gateway_mappings['Multiple1']
185193
gateway_name = self.new_gateway_name
186-
chassis = self.select(mapping, gateway_name)
194+
chassis = self.select(mapping, gateway_name,
195+
candidates=mapping['Chassis'])
187196
self.assertCountEqual(chassis, mapping.get('Chassis'))
188197
# least loaded will be the first one in the list,
189198
# networking-ovn will assign highest priority to this first element
@@ -192,28 +201,32 @@ def test_least_loaded_chassis_available_for_new_gateway1(self):
192201
def test_least_loaded_chassis_available_for_new_gateway2(self):
193202
mapping = self.fake_chassis_gateway_mappings['Multiple2']
194203
gateway_name = self.new_gateway_name
195-
chassis = self.select(mapping, gateway_name)
204+
chassis = self.select(mapping, gateway_name,
205+
candidates=mapping['Chassis'])
196206
# hv1 will have least priority
197207
self.assertEqual(chassis[2], 'hv1')
198208

199209
def test_least_loaded_chassis_available_for_new_gateway3(self):
200210
mapping = self.fake_chassis_gateway_mappings['Multiple3']
201211
gateway_name = self.new_gateway_name
202-
chassis = self.select(mapping, gateway_name)
212+
chassis = self.select(mapping, gateway_name,
213+
candidates=mapping['Chassis'])
203214
# least loaded chassis will be in the front of the list
204215
self.assertEqual(['hv1', 'hv3', 'hv2'], chassis)
205216

206217
def test_least_loaded_chassis_with_rebalance(self):
207218
mapping = self.fake_chassis_gateway_mappings['Multiple4']
208219
gateway_name = self.new_gateway_name
209-
chassis = self.select(mapping, gateway_name)
220+
chassis = self.select(mapping, gateway_name,
221+
candidates=mapping['Chassis'])
210222
# least loaded chassis will be in the front of the list
211223
self.assertEqual(['hv2', 'hv1'], chassis)
212224

213225
def test_existing_chassis_available_for_existing_gateway(self):
214226
mapping = self.fake_chassis_gateway_mappings['Multiple1']
215227
gateway_name = random.choice(list(mapping['Gateways'].keys()))
216-
chassis = self.select(mapping, gateway_name)
228+
chassis = self.select(mapping, gateway_name,
229+
candidates=mapping['Chassis'])
217230
self.assertEqual(ovn_const.MAX_GW_CHASSIS, len(chassis))
218231

219232
def test__get_chassis_load_by_prios_several_ports(self):

neutron/tests/unit/services/ovn_l3/test_plugin.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
from neutron.api.v2 import router as api_router
3535
from neutron.common.ovn import constants as ovn_const
3636
from neutron.common.ovn import utils
37+
from neutron.conf.plugins.ml2.drivers import driver_type as driver_type_conf
3738
from neutron.conf.plugins.ml2.drivers.ovn import ovn_conf as config
3839
from neutron.db import extraroute_db
3940
from neutron import manager as neutron_manager
@@ -65,6 +66,7 @@ def _start_mock(self, path, return_value, new_callable=None):
6566
def setUp(self):
6667
mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb.'
6768
'impl_idl_ovn.Backend.schema_helper').start()
69+
driver_type_conf.register_ml2_drivers_geneve_opts(cfg=cfg.CONF)
6870
cfg.CONF.set_override('max_header_size', 38, group='ml2_type_geneve')
6971
super(TestOVNL3RouterPlugin, self).setUp()
7072
revision_plugin.RevisionPlugin()
@@ -1559,12 +1561,10 @@ def test_schedule_unhosted_gateways(self, get_gppm):
15591561
chassis_physnets=chassis_mappings,
15601562
cms=chassis, availability_zone_hints=[])] * 3)
15611563
self.mock_schedule.assert_has_calls([
1562-
mock.call(self.nb_idl(), self.sb_idl(),
1563-
'lrp-foo-1', [], ['chassis1', 'chassis2']),
1564-
mock.call(self.nb_idl(), self.sb_idl(),
1565-
'lrp-foo-2', [], ['chassis2']),
1566-
mock.call(self.nb_idl(), self.sb_idl(),
1567-
'lrp-foo-3', [], [])])
1564+
mock.call(self.nb_idl(), 'lrp-foo-1', [],
1565+
['chassis1', 'chassis2']),
1566+
mock.call(self.nb_idl(), 'lrp-foo-2', [], ['chassis2']),
1567+
mock.call(self.nb_idl(), 'lrp-foo-3', [], [])])
15681568
# make sure that for second port primary chassis stays untouched
15691569
self.nb_idl().update_lrouter_port.assert_has_calls([
15701570
mock.call('lrp-foo-1',
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
features:
3+
- |
4+
Remote address group support was added to the iptables-based firewall
5+
drivers (IptablesFirewallDriver and OVSHybridIptablesFirewallDriver),
6+
Previously it was only available in the OVSFirewallDriver.
7+
For more information, see bug
8+
`2058138 <https://bugs.launchpad.net/neutron/+bug/2058138>`_.

0 commit comments

Comments
 (0)