Skip to content

Commit 4eba379

Browse files
committed
Fix behaviour of enable/disable in OVN network log
Previously, only the first log object created that associated to a certain ACL would be able to make changes to the True/False property of that ACL. This patch makes the driver to take in consideration each log object created to enable or disable an ACL logging status. A functional test is added so as to ensure correct behaviour of this feature. Closes-Bug: #1996780 Change-Id: Ib9663495f30562f79babef163729a0c43812089d Signed-off-by: Elvira García <[email protected]> (cherry picked from commit f629b77)
1 parent 1183240 commit 4eba379

File tree

2 files changed

+102
-4
lines changed

2 files changed

+102
-4
lines changed

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

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,46 @@ def create_log_precommit(self, context, log_obj):
302302
if not self.network_logging_supported(self.ovn_nb):
303303
raise LoggingNotSupported()
304304

305+
def _unset_disabled_acls(self, context, log_obj, ovn_txn):
306+
"""Check if we need to disable any ACLs after an update.
307+
308+
Will return True if there were more logs, and False if there was
309+
nothing to check.
310+
311+
:param context: current running context information
312+
:param log_obj: a log_object which was updated
313+
:returns: True if there were other logs enabled, otherwise False.
314+
"""
315+
if log_obj.enabled:
316+
return False
317+
318+
pgs = self._pgs_from_log_obj(context, log_obj)
319+
other_logs = [log for log in self._get_logs(context)
320+
if log.id != log_obj.id and log.enabled]
321+
if not other_logs:
322+
return False
323+
324+
if log_obj.event == log_const.ALL_EVENT:
325+
acls_to_check = pgs[0]["acls"].copy()
326+
if not acls_to_check:
327+
return True
328+
for log in other_logs:
329+
for acl in self._pgs_from_log_obj(context, log)[0]["acls"]:
330+
if acl in acls_to_check:
331+
acls_to_check.remove(acl)
332+
if not acls_to_check:
333+
return True
334+
acls_to_remove = [{"name": pgs[0]["name"], "acls": acls_to_check}]
335+
self._remove_acls_log(acls_to_remove, ovn_txn)
336+
else:
337+
all_events = set([log.event for log in other_logs
338+
if (not log.resource_id or
339+
log.resource_id == log_obj.resource_id)])
340+
if (log_const.ALL_EVENT not in all_events and
341+
log_obj.event not in all_events):
342+
self._remove_acls_log(pgs, ovn_txn)
343+
return True
344+
305345
def update_log(self, context, log_obj):
306346
"""Update a log_obj invocation.
307347
@@ -311,11 +351,13 @@ def update_log(self, context, log_obj):
311351
"""
312352
LOG.debug("Update_log %s", log_obj)
313353

314-
pgs = self._pgs_from_log_obj(context, log_obj)
315-
actions_enabled = self._acl_actions_enabled(log_obj)
316354
with self.ovn_nb.transaction(check_error=True) as ovn_txn:
317-
self._set_acls_log(pgs, ovn_txn, actions_enabled,
318-
utils.ovn_name(log_obj.id))
355+
356+
if not self._unset_disabled_acls(context, log_obj, ovn_txn):
357+
pgs = self._pgs_from_log_obj(context, log_obj)
358+
actions_enabled = self._acl_actions_enabled(log_obj)
359+
self._set_acls_log(pgs, ovn_txn, actions_enabled,
360+
utils.ovn_name(log_obj.id))
319361

320362
def delete_log(self, context, log_obj):
321363
"""Delete a log_obj invocation.

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

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,3 +338,59 @@ def test_events_one_sg(self):
338338
self._add_logs_then_remove(
339339
log_const.DROP_EVENT, log_const.ACCEPT_EVENT, sg=self.sg3,
340340
sgrs=self.sg3rs)
341+
342+
def test_disable_logs(self):
343+
# This test ensures that acls are correctly disabled when having
344+
# multiple log objects.
345+
346+
# Check there are no acls with their logging active
347+
sgrs = self.sg1rs
348+
self._check_sgrs(sgrs, is_enabled=False)
349+
self._check_acl_log_drop(is_enabled=False)
350+
351+
# Add accept log object
352+
log_data1 = self._log_data(sg_id=self.sg1)
353+
event1 = log_const.ACCEPT_EVENT
354+
log_data1['log']['event'] = event1
355+
log_obj1 = self.log_plugin.create_log(self.ctxt, log_data1)
356+
self._check_acl_log_drop(is_enabled=False)
357+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
358+
359+
# Add drop log object
360+
log_data2 = self._log_data(sg_id=self.sg1)
361+
event2 = log_const.DROP_EVENT
362+
log_data2['log']['event'] = event2
363+
log_obj2 = self.log_plugin.create_log(self.ctxt, log_data2)
364+
self._check_acl_log_drop(is_enabled=True)
365+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
366+
367+
# Disable drop log object and check it worked correctly
368+
log_data2['log']['enabled'] = False
369+
self.log_plugin.update_log(self.ctxt, log_obj2['id'], log_data2)
370+
self._check_acl_log_drop(is_enabled=False)
371+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
372+
373+
# Enable drop log and create all log object
374+
log_data2['log']['enabled'] = True
375+
self.log_plugin.update_log(self.ctxt, log_obj2['id'], log_data2)
376+
self._check_acl_log_drop(is_enabled=True)
377+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
378+
379+
log_data3 = self._log_data(sg_id=self.sg1)
380+
log_data3['log']['event'] = log_const.ALL_EVENT
381+
log_obj3 = self.log_plugin.create_log(self.ctxt, log_data3)
382+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
383+
self._check_acl_log_drop(is_enabled=True)
384+
385+
# Disable all log object and check all acls are still enabled (because
386+
# of the other objects)
387+
log_data3['log']['enabled'] = False
388+
self.log_plugin.update_log(self.ctxt, log_obj3['id'], log_data3)
389+
self._check_sgrs(sgrs=sgrs, is_enabled=True)
390+
self._check_acl_log_drop(is_enabled=True)
391+
392+
# Disable accept log object and only drop traffic gets logged
393+
log_data1['log']['enabled'] = False
394+
self.log_plugin.update_log(self.ctxt, log_obj1['id'], log_data1)
395+
self._check_sgrs(sgrs=sgrs, is_enabled=False)
396+
self._check_acl_log_drop(is_enabled=True)

0 commit comments

Comments
 (0)