Skip to content

Commit bdb697f

Browse files
authored
Merge pull request #69 from stackhpc/upstream/yoga-2023-10-16
Synchronise yoga with upstream
2 parents 6799634 + 95caa53 commit bdb697f

File tree

8 files changed

+174
-40
lines changed

8 files changed

+174
-40
lines changed

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

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,7 +2733,8 @@ def add_txns_to_remove_port_dns_records(self, txn, port):
27332733
txn.add(self._nb_idl.dns_remove_record(
27342734
ls_dns_record.uuid, ptr_record, if_exists=True))
27352735

2736-
def create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None):
2736+
def _create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None,
2737+
stateless=False):
27372738
"""Create row in Meter table with fair attribute set to True.
27382739
27392740
Create a row in OVN's NB Meter table based on well-known name. This
@@ -2748,21 +2749,35 @@ def create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None):
27482749
"""
27492750
meter = self._nb_idl.db_find_rows(
27502751
"Meter", ("name", "=", meter_name)).execute(check_error=True)
2751-
# The meter is created when a log object is created, not by default.
2752-
# This condition avoids creating the meter if it wasn't there already
2752+
# The meters are created when a log object is created, not by default.
2753+
# This condition avoids creating the meter if it wasn't there already.
27532754
commands = []
27542755
if from_reload and not meter:
27552756
return
2757+
2758+
burst_limit = cfg.CONF.network_log.burst_limit
2759+
rate_limit = cfg.CONF.network_log.rate_limit
2760+
if stateless:
2761+
meter_name = meter_name + "_stateless"
2762+
burst_limit = int(burst_limit / 2)
2763+
rate_limit = int(rate_limit / 2)
2764+
# The stateless meter is only created once the stateful meter was
2765+
# successfully created.
2766+
# The treatment of limits is not equal for stateful and stateless
2767+
# traffic at a kernel level according to:
2768+
# https://bugzilla.redhat.com/show_bug.cgi?id=2212952
2769+
# The stateless meter is created to adjust this issue.
2770+
meter = self._nb_idl.db_find_rows(
2771+
"Meter", ("name", "=", meter_name)).execute(check_error=True)
27562772
if meter:
27572773
meter = meter[0]
27582774
meter_band = self._nb_idl.lookup("Meter_Band",
27592775
meter.bands[0].uuid, default=None)
27602776
if meter_band:
27612777
if all((meter.unit == "pktps",
27622778
meter.fair[0],
2763-
meter_band.rate == cfg.CONF.network_log.rate_limit,
2764-
meter_band.burst_size ==
2765-
cfg.CONF.network_log.burst_limit)):
2779+
meter_band.rate == rate_limit,
2780+
meter_band.burst_size == burst_limit)):
27662781
# Meter (and its meter-band) unchanged: noop.
27672782
return
27682783
# Re-create meter (and its meter-band) with the new attributes.
@@ -2776,10 +2791,15 @@ def create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None):
27762791
commands.append(self._nb_idl.meter_add(
27772792
name=meter_name,
27782793
unit="pktps",
2779-
rate=cfg.CONF.network_log.rate_limit,
2794+
rate=rate_limit,
27802795
fair=True,
2781-
burst_size=cfg.CONF.network_log.burst_limit,
2796+
burst_size=burst_limit,
27822797
may_exist=False,
27832798
external_ids={ovn_const.OVN_DEVICE_OWNER_EXT_ID_KEY:
27842799
log_const.LOGGING_PLUGIN}))
27852800
self._transaction(commands, txn=txn)
2801+
2802+
def create_ovn_fair_meter(self, meter_name, from_reload=False, txn=None):
2803+
self._create_ovn_fair_meter(meter_name, from_reload, txn)
2804+
self._create_ovn_fair_meter(meter_name, from_reload, txn,
2805+
stateless=True)

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,11 +424,13 @@ def __init__(self, driver):
424424
self.l3_plugin = directory.get_plugin(constants.L3)
425425
table = 'Port_Binding'
426426
events = (self.ROW_UPDATE,)
427-
super(PortBindingChassisEvent, self).__init__(
428-
events, table, (('type', '=', ovn_const.OVN_CHASSIS_REDIRECT),))
427+
super().__init__(events, table, None)
429428
self.event_name = 'PortBindingChassisEvent'
430429

431430
def match_fn(self, event, row, old):
431+
if row.type != ovn_const.OVN_CHASSIS_REDIRECT:
432+
return False
433+
432434
if len(old._data) == 1 and 'external_ids' in old._data:
433435
# NOTE: since [1], the NB logical_router_port.external_ids are
434436
# copied into the SB port_binding.external_ids. If only the

neutron/services/logapi/drivers/ovn/driver.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from neutron.common.ovn import constants as ovn_const
2929
from neutron.common.ovn import utils
3030
from neutron.conf.services import logging as log_cfg
31+
from neutron.objects import securitygroup as sg_obj
3132
from neutron.services.logapi.common import db_api
3233
from neutron.services.logapi.common import sg_callback
3334
from neutron.services.logapi.drivers import base
@@ -152,9 +153,21 @@ def _remove_acls_log(self, pgs, ovn_txn, log_name=None):
152153
msg += " for network log {}".format(log_name)
153154
LOG.info(msg, acl_changes, acl_absents, acl_visits)
154155

155-
def _set_acls_log(self, pgs, ovn_txn, actions_enabled, log_name):
156+
def _set_acls_log(self, pgs, context, ovn_txn, actions_enabled, log_name):
156157
acl_changes, acl_visits = 0, 0
157158
for pg in pgs:
159+
meter_name = self.meter_name
160+
if pg["name"] != ovn_const.OVN_DROP_PORT_GROUP_NAME:
161+
sg = sg_obj.SecurityGroup.get_sg_by_id(
162+
context,
163+
pg["external_ids"][ovn_const.OVN_SG_EXT_ID_KEY])
164+
if not sg:
165+
LOG.warning("Port Group %s is missing a corresponding "
166+
"security group, skipping its network log "
167+
"setting...", pg["name"])
168+
continue
169+
if not sg.stateful:
170+
meter_name = meter_name + ("_stateless")
158171
for acl_uuid in pg["acls"]:
159172
acl_visits += 1
160173
acl = self.ovn_nb.lookup("ACL", acl_uuid)
@@ -163,7 +176,7 @@ def _set_acls_log(self, pgs, ovn_txn, actions_enabled, log_name):
163176
continue
164177
columns = {
165178
'log': acl.action in actions_enabled,
166-
'meter': self.meter_name,
179+
'meter': meter_name,
167180
'name': log_name,
168181
'severity': "info"
169182
}
@@ -183,12 +196,13 @@ def _update_log_objs(self, context, ovn_txn, log_objs):
183196
for log_obj in log_objs:
184197
pgs = self._pgs_from_log_obj(context, log_obj)
185198
actions_enabled = self._acl_actions_enabled(log_obj)
186-
self._set_acls_log(pgs, ovn_txn, actions_enabled,
199+
self._set_acls_log(pgs, context, ovn_txn, actions_enabled,
187200
utils.ovn_name(log_obj.id))
188201

189202
def _pgs_all(self):
190203
return self.ovn_nb.db_list(
191-
"Port_Group", columns=["name", "acls"]).execute(check_error=True)
204+
"Port_Group",
205+
columns=["name", "external_ids", "acls"]).execute(check_error=True)
192206

193207
def _pgs_from_log_obj(self, context, log_obj):
194208
"""Map Neutron log_obj into affected port groups in OVN.
@@ -207,11 +221,13 @@ def _pgs_from_log_obj(self, context, log_obj):
207221
# No sg, no port, DROP: return DROP pg
208222
if log_obj.event == log_const.DROP_EVENT:
209223
return [{"name": pg_drop.name,
210-
"acls": [r.uuid for r in pg_drop.acls]}]
224+
"external_ids": pg_drop.external_ids,
225+
"acls": [r.uuid for r in pg_drop.acls]}]
211226
# No sg, no port, ACCEPT: return all except DROP pg
212227
pgs = self._pgs_all()
213228
pgs.remove({"name": pg_drop.name,
214-
"acls": [r.uuid for r in pg_drop.acls]})
229+
"external_ids": pg_drop.external_ids,
230+
"acls": [r.uuid for r in pg_drop.acls]})
215231
return pgs
216232
except idlutils.RowNotFound:
217233
pass
@@ -223,6 +239,7 @@ def _pgs_from_log_obj(self, context, log_obj):
223239
pg = self.ovn_nb.lookup("Port_Group",
224240
ovn_const.OVN_DROP_PORT_GROUP_NAME)
225241
pgs.append({"name": pg.name,
242+
"external_ids": pg.external_ids,
226243
"acls": [r.uuid for r in pg.acls]})
227244
except idlutils.RowNotFound:
228245
pass
@@ -235,6 +252,7 @@ def _pgs_from_log_obj(self, context, log_obj):
235252
utils.ovn_port_group_name(
236253
log_obj.resource_id))
237254
pgs.append({"name": pg.name,
255+
"external_ids": pg.external_ids,
238256
"acls": [r.uuid for r in pg.acls]})
239257
except idlutils.RowNotFound:
240258
pass
@@ -248,6 +266,7 @@ def _pgs_from_log_obj(self, context, log_obj):
248266
pg = self.ovn_nb.lookup("Port_Group",
249267
utils.ovn_port_group_name(sg_id))
250268
pgs.append({"name": pg.name,
269+
"external_ids": pg.external_ids,
251270
"acls": [r.uuid for r in pg.acls]})
252271
except idlutils.RowNotFound:
253272
pass
@@ -266,7 +285,7 @@ def create_log(self, context, log_obj):
266285
with self.ovn_nb.transaction(check_error=True) as ovn_txn:
267286
self._ovn_client.create_ovn_fair_meter(self.meter_name,
268287
txn=ovn_txn)
269-
self._set_acls_log(pgs, ovn_txn, actions_enabled,
288+
self._set_acls_log(pgs, context, ovn_txn, actions_enabled,
270289
utils.ovn_name(log_obj.id))
271290

272291
def create_log_precommit(self, context, log_obj):
@@ -334,7 +353,7 @@ def update_log(self, context, log_obj):
334353
if not self._unset_disabled_acls(context, log_obj, ovn_txn):
335354
pgs = self._pgs_from_log_obj(context, log_obj)
336355
actions_enabled = self._acl_actions_enabled(log_obj)
337-
self._set_acls_log(pgs, ovn_txn, actions_enabled,
356+
self._set_acls_log(pgs, context, ovn_txn, actions_enabled,
338357
utils.ovn_name(log_obj.id))
339358

340359
def delete_log(self, context, log_obj):
@@ -356,6 +375,8 @@ def delete_log(self, context, log_obj):
356375
self._remove_acls_log(pgs, ovn_txn)
357376
ovn_txn.add(self.ovn_nb.meter_del(self.meter_name,
358377
if_exists=True))
378+
ovn_txn.add(self.ovn_nb.meter_del(
379+
self.meter_name + "_stateless", if_exists=True))
359380
LOG.info("All ACL logs cleared after deletion of log_obj %s",
360381
log_obj.id)
361382
return

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,10 +1125,9 @@ def test_check_for_logging_conf_change(self):
11251125
# Check a meter and fair meter exist
11261126
self.assertTrue(self.nb_api._tables['Meter'].rows)
11271127
self.assertTrue(self.nb_api._tables['Meter_Band'].rows)
1128-
self.assertEqual(cfg.CONF.network_log.burst_limit,
1129-
[*self.nb_api._tables['Meter_Band'].rows.values()][0].burst_size)
1130-
self.assertEqual(cfg.CONF.network_log.rate_limit,
1131-
[*self.nb_api._tables['Meter_Band'].rows.values()][0].rate)
1128+
self.assertEqual(len([*self.nb_api._tables['Meter'].rows.values()]),
1129+
len([*self.nb_api._tables['Meter_Band'].rows.values()]))
1130+
self._check_meters_consistency()
11321131
# Update burst and rate limit values on the configuration
11331132
ovn_config.cfg.CONF.set_override('burst_limit', CFG_NEW_BURST,
11341133
group='network_log')
@@ -1138,7 +1137,16 @@ def test_check_for_logging_conf_change(self):
11381137
self.assertRaises(periodics.NeverAgain,
11391138
self.maint.check_fair_meter_consistency)
11401139
# Check meter band was effectively changed after the maintenance call
1141-
self.assertEqual(CFG_NEW_BURST,
1142-
[*self.nb_api._tables['Meter_Band'].rows.values()][0].burst_size)
1143-
self.assertEqual(CFG_NEW_RATE,
1144-
[*self.nb_api._tables['Meter_Band'].rows.values()][0].rate)
1140+
self._check_meters_consistency(CFG_NEW_BURST, CFG_NEW_RATE)
1141+
1142+
def _check_meters_consistency(self, new_burst=None, new_rate=None):
1143+
burst, rate = (new_burst, new_rate) if new_burst else (
1144+
cfg.CONF.network_log.burst_limit, cfg.CONF.network_log.rate_limit)
1145+
for meter in [*self.nb_api._tables['Meter'].rows.values()]:
1146+
meter_band = self.nb_api.lookup('Meter_Band', meter.bands[0].uuid)
1147+
if "_stateless" in meter.name:
1148+
self.assertEqual(int(burst / 2), meter_band.burst_size)
1149+
self.assertEqual(int(rate / 2), meter_band.rate)
1150+
else:
1151+
self.assertEqual(burst, meter_band.burst_size)
1152+
self.assertEqual(rate, meter_band.rate)

neutron/tests/functional/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_ovsdb_monitor.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,3 +577,45 @@ def test_ovsdb_probe_interval(self):
577577
interval = ovn_conf.get_ovn_ovsdb_probe_interval()
578578
for idl in idls:
579579
self.assertEqual(interval, idl._session.reconnect.probe_interval)
580+
581+
582+
class TestPortBindingChassisEvent(base.TestOVNFunctionalBase,
583+
test_l3.L3NatTestCaseMixin):
584+
585+
def setUp(self, **kwargs):
586+
super().setUp(**kwargs)
587+
self.chassis = self.add_fake_chassis('ovs-host1')
588+
self.l3_plugin = directory.get_plugin(plugin_constants.L3)
589+
kwargs = {'arg_list': (external_net.EXTERNAL,),
590+
external_net.EXTERNAL: True}
591+
self.net = self._make_network(
592+
self.fmt, 'ext_net', True, as_admin=True, **kwargs)
593+
self._make_subnet(self.fmt, self.net, '20.0.10.1', '20.0.10.0/24')
594+
port_res = self._create_port(self.fmt, self.net['network']['id'])
595+
self.port = self.deserialize(self.fmt, port_res)['port']
596+
597+
self.ext_api = test_extensions.setup_extensions_middleware(
598+
test_l3.L3TestExtensionManager())
599+
self.pb_event_match = mock.patch.object(
600+
self.sb_api.idl._portbinding_event, 'match_fn').start()
601+
602+
def _check_pb_type(self, _type):
603+
def check_pb_type(_type):
604+
if len(self.pb_event_match.call_args_list) < 1:
605+
return False
606+
607+
pb_row = self.pb_event_match.call_args_list[0].args[1]
608+
return _type == pb_row.type
609+
610+
n_utils.wait_until_true(lambda: check_pb_type(_type), timeout=5)
611+
612+
def test_pb_type_patch(self):
613+
router = self._make_router(self.fmt, self._tenant_id)
614+
self._add_external_gateway_to_router(router['router']['id'],
615+
self.net['network']['id'])
616+
self._check_pb_type('patch')
617+
618+
def test_pb_type_empty(self):
619+
self.sb_api.lsp_bind(self.port['id'], self.chassis,
620+
may_exist=True).execute(check_error=True)
621+
self._check_pb_type('')

neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ def setUp(self):
3030
self._check_is_supported()
3131
self.ctxt = context.Context('admin', 'fake_tenant')
3232

33+
# Since these tests use the _create_network() from the unit test suite
34+
# but _create_security_group() is from the functional tests, two
35+
# different tenant_ids will be used unless we specify the following
36+
# line in the code:
37+
self._tenant_id = self.ctxt.project_id
38+
3339
def _check_is_supported(self):
3440
if not self.log_driver.network_logging_supported(self.nb_api):
3541
self.skipTest("The current OVN version does not offer support "

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,16 @@ def test_create_ovn_fair_meter(self):
247247
self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name)
248248
self.assertFalse(self.nb_idl.meter_del.called)
249249
self.assertTrue(self.nb_idl.meter_add.called)
250-
self.nb_idl.meter_add.assert_called_once_with(
250+
self.nb_idl.meter_add.assert_any_call(
251+
name=self._log_driver.meter_name + "_stateless",
252+
unit="pktps",
253+
rate=int(self.fake_cfg_network_log.rate_limit / 2),
254+
fair=True,
255+
burst_size=int(self.fake_cfg_network_log.burst_limit / 2),
256+
may_exist=False,
257+
external_ids={constants.OVN_DEVICE_OWNER_EXT_ID_KEY:
258+
log_const.LOGGING_PLUGIN})
259+
self.nb_idl.meter_add.assert_any_call(
251260
name=self._log_driver.meter_name,
252261
unit="pktps",
253262
rate=self.fake_cfg_network_log.rate_limit,
@@ -259,10 +268,17 @@ def test_create_ovn_fair_meter(self):
259268

260269
def test_create_ovn_fair_meter_unchanged(self):
261270
mock_find_rows = mock.Mock()
262-
mock_find_rows.execute.return_value = [self._fake_meter()]
271+
fake_meter1 = [self._fake_meter()]
272+
fake_meter2 = [self._fake_meter(
273+
name=self._log_driver.meter_name + "_stateless",
274+
bands=[mock.Mock(uuid='tb_stateless')])]
275+
mock_find_rows.execute.side_effect = [fake_meter1, fake_meter1,
276+
fake_meter2, fake_meter2]
263277
self.nb_idl.db_find_rows.return_value = mock_find_rows
264278
self.nb_idl.lookup.side_effect = lambda table, key, default: (
265-
self._fake_meter_band() if key == "test_band" else default)
279+
self._fake_meter_band() if key == "test_band" else
280+
self._fake_meter_band_stateless() if key == "tb_stateless" else
281+
default)
266282
self.ovn_client.create_ovn_fair_meter(self._log_driver.meter_name)
267283
self.assertFalse(self.nb_idl.meter_del.called)
268284
self.assertFalse(self.nb_idl.meter_add.called)

0 commit comments

Comments
 (0)