diff --git a/neutron/services/logapi/drivers/ovn/driver.py b/neutron/services/logapi/drivers/ovn/driver.py index 98ed3f29ec9..5bea32a1ec2 100644 --- a/neutron/services/logapi/drivers/ovn/driver.py +++ b/neutron/services/logapi/drivers/ovn/driver.py @@ -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 @@ -38,6 +39,7 @@ log_cfg.register_log_driver_opts() +MAX_INT_LABEL = 2**32 SUPPORTED_LOGGING_TYPES = [log_const.SECURITY_GROUP] @@ -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: @@ -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) diff --git a/neutron/tests/functional/agent/l3/framework.py b/neutron/tests/functional/agent/l3/framework.py index 45de9ac8278..c30c44cbf49 100644 --- a/neutron/tests/functional/agent/l3/framework.py +++ b/neutron/tests/functional/agent/l3/framework.py @@ -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) @@ -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 @@ -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) diff --git a/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py b/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py index 03f1d365d62..57c7978b8fc 100644 --- a/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py +++ b/neutron/tests/functional/services/logapi/drivers/ovn/test_driver.py @@ -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): diff --git a/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py b/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py index 1afa735c10a..35c2ec5765a 100644 --- a/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py +++ b/neutron/tests/unit/services/logapi/drivers/ovn/test_driver.py @@ -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): diff --git a/releasenotes/notes/sgl-log-related-traffic-ovn-96b304ab744de13e.yaml b/releasenotes/notes/sgl-log-related-traffic-ovn-96b304ab744de13e.yaml new file mode 100644 index 00000000000..b3ea740aa54 --- /dev/null +++ b/releasenotes/notes/sgl-log-related-traffic-ovn-96b304ab744de13e.yaml @@ -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#`