From 5d94a10a1507625a861585bc83a295fb9442704e Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Fri, 1 Oct 2021 17:03:26 +0000 Subject: [PATCH] [OVN] Check if OVN NB supports "Port_Group" Added a check for OVN NB schema, looking for "Port_Group" table (added in OVN NB schema 5.11). This patch removes the code to support OVN without "Port_Group" table. It is assumed that this table is always present. Closes-Bug: #1946023 Change-Id: If193ff5bc6e1421f4fa9db3779872a82a36c8b69 --- neutron/cmd/sanity/checks.py | 44 +++++++++++++++++++ neutron/cmd/sanity_check.py | 14 ++++++ .../ovn/mech_driver/ovsdb/impl_idl_ovn.py | 34 +++++--------- .../mech_driver/ovsdb/test_impl_idl_ovn.py | 15 ------- ...-supports-Port_Group-96fc1a89e2da163d.yaml | 7 +++ 5 files changed, 75 insertions(+), 39 deletions(-) create mode 100644 releasenotes/notes/ovn-supports-Port_Group-96fc1a89e2da163d.yaml diff --git a/neutron/cmd/sanity/checks.py b/neutron/cmd/sanity/checks.py index 0e01c21b459..6a9fb4bfded 100644 --- a/neutron/cmd/sanity/checks.py +++ b/neutron/cmd/sanity/checks.py @@ -14,6 +14,7 @@ # under the License. import distutils +import enum import re import shutil import tempfile @@ -49,6 +50,35 @@ DNSMASQ_VERSION_HOST_ADDR6_LIST = '2.81' DIRECT_PORT_QOS_MIN_OVS_VERSION = '2.11' MINIMUM_DIBBLER_VERSION = '1.0.1' CONNTRACK_GRE_MODULE = 'nf_conntrack_proto_gre' +OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11' + + +class OVNCheckType(enum.Enum): + nb_version = 0 + nb_db_schema = 1 + sb_version = 2 + sb_db_schema = 3 + + +def _get_ovn_version(check_type): + if check_type in (OVNCheckType.nb_version, OVNCheckType.nb_db_schema): + cmd = ['ovn-nbctl', '--version'] + elif check_type in (OVNCheckType.nb_version, OVNCheckType.nb_db_schema): + cmd = ['ovn-sbctl', '--version'] + else: + raise RuntimeError + + out = agent_utils.execute(cmd) + if check_type == OVNCheckType.nb_version: + matched_line = re.search(r"ovn-nbctl.*", out) + elif check_type == OVNCheckType.sb_version: + matched_line = re.search(r"ovn-sbctl.*", out) + else: + matched_line = re.search(r"DB Schema.*", out) + + matched_version = re.search(r"(\d+\.\d+)", matched_line.group(0)) + return versionutils.convert_version_to_tuple(matched_version.group(1) if + matched_version else '0.0') def ovs_vxlan_supported(from_ip='192.0.2.1', to_ip='192.0.2.2'): @@ -551,3 +581,17 @@ def min_tx_rate_support(): devices_without_support) return False return True + + +def ovn_nb_db_schema_port_group_supported(): + try: + ver = _get_ovn_version(OVNCheckType.nb_db_schema) + minver = versionutils.convert_version_to_tuple( + OVN_NB_DB_SCHEMA_PORT_GROUP) + if ver < minver: + return False + except (OSError, RuntimeError, ValueError) as e: + LOG.debug('Exception while checking OVN DB schema version. ' + 'Exception: %s', e) + return False + return True diff --git a/neutron/cmd/sanity_check.py b/neutron/cmd/sanity_check.py index ff778e09315..ccebedf9462 100644 --- a/neutron/cmd/sanity_check.py +++ b/neutron/cmd/sanity_check.py @@ -303,6 +303,14 @@ def check_min_tx_rate_support(): return result +def check_ovn_nb_db_schema_port_group_support(): + result = checks.ovn_nb_db_schema_port_group_supported() + if not result: + LOG.warning('OVN NB DB schema does not support Port_Group. This ' + 'support was added in DB schema version 5.11.') + return result + + # Define CLI opts to test specific features, with a callback for the test OPTS = [ BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False, @@ -367,6 +375,10 @@ OPTS = [ help=_('Check if the configured SR-IOV NICs support ' 'the "ip-link vf min_tx_rate" parameter.'), default=False), + BoolOptCallback('ovn_nb_db_schema_port_group_support', + check_ovn_nb_db_schema_port_group_support, + help=_('Check OVN NB DB schema support Port_Group'), + default=False), ] @@ -413,6 +425,8 @@ def enable_tests_from_config(): cfg.CONF.set_default('bridge_firewalling', True) if cfg.CONF.SRIOV_NIC.physical_device_mappings: cfg.CONF.set_default('check_min_tx_rate_support', True) + if 'ovn' in cfg.CONF.ml2.mechanism_drivers: + cfg.CONF.set_default('ovn_nb_db_schema_port_group_support', True) def all_tests_passed(): diff --git a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py index a0a106793dc..785f0ef142a 100644 --- a/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py +++ b/neutron/plugins/ml2/drivers/ovn/mech_driver/ovsdb/impl_idl_ovn.py @@ -770,14 +770,7 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend): def get_port_group(self, pg_name): if uuidutils.is_uuid_like(pg_name): pg_name = utils.ovn_port_group_name(pg_name) - try: - return self.lookup('Port_Group', pg_name, default=None) - except KeyError: - # TODO(dalvarez): This except block is added for backwards compat - # with old OVN schemas (<=2.9) where Port Groups are not present. - # This (and other conditional code around this feature) shall be - # removed at some point. - return + return self.lookup('Port_Group', pg_name, default=None) def get_sg_port_groups(self): """Returns OVN port groups used as Neutron Security Groups. @@ -787,22 +780,15 @@ class OvsdbNbOvnIdl(nb_impl_idl.OvnNbApiIdlImpl, Backend): SGs, it will also not be returned. """ port_groups = {} - try: - for row in self._tables['Port_Group'].rows.values(): - name = getattr(row, 'name') - if not (ovn_const.OVN_SG_EXT_ID_KEY in row.external_ids or - name == ovn_const.OVN_DROP_PORT_GROUP_NAME): - continue - data = {} - for row_key in getattr(row, "_data", {}): - data[row_key] = getattr(row, row_key) - port_groups[name] = data - except KeyError: - # TODO(dalvarez): This except block is added for backwards compat - # with old OVN schemas (<=2.9) where Port Groups are not present. - # This (and other conditional code around this feature) shall be - # removed at some point. - pass + for row in self._tables['Port_Group'].rows.values(): + name = getattr(row, 'name') + if not (ovn_const.OVN_SG_EXT_ID_KEY in row.external_ids or + name == ovn_const.OVN_DROP_PORT_GROUP_NAME): + continue + data = {} + for row_key in getattr(row, "_data", {}): + data[row_key] = getattr(row, row_key) + port_groups[name] = data return port_groups def check_liveness(self): diff --git a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py index 32b9490965a..1b62ad4c8f1 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py +++ b/neutron/tests/unit/plugins/ml2/drivers/ovn/mech_driver/ovsdb/test_impl_idl_ovn.py @@ -14,7 +14,6 @@ import collections import copy from unittest import mock -import uuid from ovsdbapp.backend import ovs_idl @@ -769,20 +768,6 @@ class TestNBImplIdlOvn(TestDBImplIdlOvn): address_sets = self.nb_ovn_idl.get_address_sets() self.assertEqual(len(address_sets), 4) - def test_get_port_group_not_supported(self): - self._load_nb_db() - # Make sure that PG tables doesn't exist in fake db. - self._tables.pop('Port_Group', None) - port_group = self.nb_ovn_idl.get_port_group(str(uuid.uuid4())) - self.assertIsNone(port_group) - - def test_get_sg_port_groups_not_supported(self): - self._load_nb_db() - # Make sure that PG tables doesn't exist in fake db. - self._tables.pop('Port_Group', None) - port_groups = self.nb_ovn_idl.get_sg_port_groups() - self.assertEqual({}, port_groups) - def test_get_router_floatingip_lbs(self): lrouter_name = 'rtr_name' # Empty diff --git a/releasenotes/notes/ovn-supports-Port_Group-96fc1a89e2da163d.yaml b/releasenotes/notes/ovn-supports-Port_Group-96fc1a89e2da163d.yaml new file mode 100644 index 00000000000..eba29d7c074 --- /dev/null +++ b/releasenotes/notes/ovn-supports-Port_Group-96fc1a89e2da163d.yaml @@ -0,0 +1,7 @@ +--- +other: + - | + It is assumed now that OVN supports Northbound table ``Port_Group`` by + default. This table was added in the DB schema version 5.11. A sanity check + is included if OVN is defined in ``ml2.mechanism_drivers`` configuration + option.