Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 28 additions & 12 deletions neutron/services/logapi/drivers/ovn/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# under the License.

from collections import namedtuple
import random

from neutron_lib.api.definitions import portbindings
from neutron_lib.callbacks import resources
Expand Down Expand Up @@ -38,6 +39,7 @@

log_cfg.register_log_driver_opts()

MAX_INT_LABEL = 2**32
SUPPORTED_LOGGING_TYPES = [log_const.SECURITY_GROUP]


Expand Down Expand Up @@ -169,13 +171,20 @@ def _remove_acls_log(self, pgs, ovn_txn, log_name=None):
if log_name:
if acl.name and acl.name[0] != log_name:
continue
columns = {
'log': False,
'meter': [],
'name': [],
'severity': []
}
# TODO(egarciar): There wont be a need to check if label exists
# once minimum version for OVN is >= 22.03
if hasattr(acl, 'label'):
columns['label'] = 0
ovn_txn.add(self.ovn_nb.db_remove(
"ACL", acl_uuid, 'options', 'log-related'))
ovn_txn.add(self.ovn_nb.db_set(
"ACL", acl_uuid,
("log", False),
("meter", []),
("name", []),
("severity", [])
))
"ACL", acl_uuid, *columns.items()))
acl_changes += 1
msg = "Cleared %d, Not found %d (out of %d visited) ACLs"
if log_name:
Expand All @@ -191,13 +200,20 @@ def _set_acls_log(self, pgs, ovn_txn, actions_enabled, log_name):
# skip acls used by a different network log
if acl.name and acl.name[0] != log_name:
continue
columns = {
'log': acl.action in actions_enabled,
'meter': self.meter_name,
'name': log_name,
'severity': "info"
}
# TODO(egarciar): There wont be a need to check if label exists
# once minimum version for OVN is >= 22.03
if hasattr(acl, "label"):
# Label needs to be an unsigned 32 bit number and not 0.
columns["label"] = random.randrange(1, MAX_INT_LABEL)
columns["options"] = {'log-related': "true"}
ovn_txn.add(self.ovn_nb.db_set(
"ACL", acl_uuid,
("log", acl.action in actions_enabled),
("meter", self.meter_name),
("name", log_name),
("severity", "info")
))
"ACL", acl_uuid, *columns.items()))
acl_changes += 1
LOG.info("Set %d (out of %d visited) ACLs for network log %s",
acl_changes, acl_visits, log_name)
Expand Down
16 changes: 6 additions & 10 deletions neutron/tests/functional/agent/l3/framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ def assert_num_of_conntrack_rules(n):
n, len([line for line in out.strip().split('\n') if line]))

if ha:
common_utils.wait_until_true(lambda: router.ha_state == 'primary')
self.wait_until_ha_router_has_state(router, 'primary')

with self.assert_max_execution_time(100):
assert_num_of_conntrack_rules(0)
Expand Down Expand Up @@ -334,7 +334,7 @@ def _router_lifecycle(self, enable_ha, ip_version=constants.IP_VERSION_4,
router.process()

if enable_ha:
common_utils.wait_until_true(lambda: router.ha_state == 'primary')
self.wait_until_ha_router_has_state(router, 'primary')

# Keepalived notifies of a state transition when it starts,
# not when it ends. Thus, we have to wait until keepalived finishes
Expand Down Expand Up @@ -669,29 +669,25 @@ def _get_primary_and_backup_routers(self, router1, router2,
check_external_device=True):

try:
common_utils.wait_until_true(
lambda: router1.ha_state == 'primary')
self.wait_until_ha_router_has_state(router1, 'primary')
if check_external_device:
common_utils.wait_until_true(
lambda: self._check_external_device(router1))
primary_router = router1
backup_router = router2
except common_utils.WaitTimeout:
common_utils.wait_until_true(
lambda: router2.ha_state == 'primary')
self.wait_until_ha_router_has_state(router2, 'primary')
if check_external_device:
common_utils.wait_until_true(
lambda: self._check_external_device(router2))
primary_router = router2
backup_router = router1

common_utils.wait_until_true(
lambda: primary_router.ha_state == 'primary')
self.wait_until_ha_router_has_state(primary_router, 'primary')
if check_external_device:
common_utils.wait_until_true(
lambda: self._check_external_device(primary_router))
common_utils.wait_until_true(
lambda: backup_router.ha_state == 'backup')
self.wait_until_ha_router_has_state(backup_router, 'backup')

LOG.debug("Found primary router %s and backup router %s",
primary_router.router_id, backup_router.router_id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,16 @@ def _check_acl_log(self, sgr, is_enabled=True):
acl = self._find_security_group_rule_row_by_id(sgr)
self.assertIsNotNone(acl)
self.assertEqual(is_enabled, acl.log)
if hasattr(acl, "label"):
# Here we compare if there is a name because the log can be
# disabled but disabling a log would not take out the properties
# attached to it.
if acl.name:
self.assertNotEqual(0, acl.label)
self.assertEqual("true", acl.options.get("log-related"))
else:
self.assertEqual(0, acl.label)
self.assertIsNone(acl.options.get("log-related"))
return acl

def _check_acl_log_drop(self, is_enabled=True):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,10 @@ def test__remove_acls_log(self, m_info):
self.assertEqual(len(pg_dict["acls"]), info_args[1])
self.assertEqual(len(pg_dict["acls"]) - 2, info_args[2])
self.assertEqual(len(pg_dict["acls"]), info_args[3])
self.assertEqual(len(pg_dict["acls"]), self._nb_ovn.db_set.call_count)
self.assertEqual(len(pg_dict["acls"]),
self._nb_ovn.db_set.call_count)
self.assertEqual(len(pg_dict["acls"]),
self._nb_ovn.db_remove.call_count)

@mock.patch.object(ovn_driver.LOG, 'info')
def test__remove_acls_log_missing_acls(self, m_info):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
Neutron can record full connection using log-related feature introduced in
OVN 21.12.
For more info see `bug LP#<https://bugs.launchpad.net/neutron/+bug/2003706>`