[OVN] Check if OVN SB supports virtual ports
Added a check for OVN SB schema, looking for "virtual_parent" in "Port_Binding" table (added in OVN SB schema 2.5). This patch removes the code to support OVN without virtual ports. It is assumed that "virtual_parent" field is present in "Port_Binding" table. Closes-Bug: #1949496 Change-Id: I3d01f58dca570537b5e754b331ca4809a7161ae2
This commit is contained in:
parent
5730eae0e9
commit
58feb88853
@ -52,6 +52,7 @@ MINIMUM_DIBBLER_VERSION = '1.0.1'
|
|||||||
CONNTRACK_GRE_MODULE = 'nf_conntrack_proto_gre'
|
CONNTRACK_GRE_MODULE = 'nf_conntrack_proto_gre'
|
||||||
OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11'
|
OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11'
|
||||||
OVN_NB_DB_SCHEMA_STATELESS_NAT = '5.17'
|
OVN_NB_DB_SCHEMA_STATELESS_NAT = '5.17'
|
||||||
|
OVN_SB_DB_SCHEMA_VIRTUAL_PORT = '2.5'
|
||||||
|
|
||||||
|
|
||||||
class OVNCheckType(enum.Enum):
|
class OVNCheckType(enum.Enum):
|
||||||
@ -612,3 +613,17 @@ def ovn_nb_db_schema_stateless_nat_supported():
|
|||||||
'Exception: %s', e)
|
'Exception: %s', e)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def ovn_sb_db_schema_virtual_port_supported():
|
||||||
|
try:
|
||||||
|
ver = _get_ovn_version(OVNCheckType.sb_db_schema)
|
||||||
|
minver = versionutils.convert_version_to_tuple(
|
||||||
|
OVN_SB_DB_SCHEMA_VIRTUAL_PORT)
|
||||||
|
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
|
||||||
|
@ -319,6 +319,14 @@ def check_ovn_nb_db_schema_stateless_nat():
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def check_ovn_sb_db_schema_virtual_port():
|
||||||
|
result = checks.ovn_sb_db_schema_virtual_port_supported()
|
||||||
|
if not result:
|
||||||
|
LOG.warning('OVN SB DB schema does not support virtual ports. This '
|
||||||
|
'support was added in DB schema version 2.5.')
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
# Define CLI opts to test specific features, with a callback for the test
|
# Define CLI opts to test specific features, with a callback for the test
|
||||||
OPTS = [
|
OPTS = [
|
||||||
BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False,
|
BoolOptCallback('ovs_vxlan', check_ovs_vxlan, default=False,
|
||||||
@ -391,6 +399,10 @@ OPTS = [
|
|||||||
check_ovn_nb_db_schema_stateless_nat,
|
check_ovn_nb_db_schema_stateless_nat,
|
||||||
help=_('Check OVN NB DB schema support stateless NAT'),
|
help=_('Check OVN NB DB schema support stateless NAT'),
|
||||||
default=False),
|
default=False),
|
||||||
|
BoolOptCallback('ovn_sb_db_schema_virtual_port_support',
|
||||||
|
check_ovn_sb_db_schema_virtual_port,
|
||||||
|
help=_('Check OVN SB DB schema support virtual ports'),
|
||||||
|
default=False),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -440,6 +452,7 @@ def enable_tests_from_config():
|
|||||||
if 'ovn' in cfg.CONF.ml2.mechanism_drivers:
|
if 'ovn' in cfg.CONF.ml2.mechanism_drivers:
|
||||||
cfg.CONF.set_default('ovn_nb_db_schema_port_group_support', True)
|
cfg.CONF.set_default('ovn_nb_db_schema_port_group_support', True)
|
||||||
cfg.CONF.set_default('ovn_nb_db_schema_stateless_nat_support', True)
|
cfg.CONF.set_default('ovn_nb_db_schema_stateless_nat_support', True)
|
||||||
|
cfg.CONF.set_default('ovn_sb_db_schema_virtual_port_support', True)
|
||||||
|
|
||||||
|
|
||||||
def all_tests_passed():
|
def all_tests_passed():
|
||||||
|
@ -105,11 +105,6 @@ class OVNClient(object):
|
|||||||
for cmd in commands:
|
for cmd in commands:
|
||||||
txn.add(cmd)
|
txn.add(cmd)
|
||||||
|
|
||||||
def _is_virtual_port_supported(self):
|
|
||||||
# TODO(lucasagomes): Remove this method in the future. The
|
|
||||||
# "virtual" port type was added in the version 2.12 of OVN
|
|
||||||
return self._sb_idl.is_col_present('Port_Binding', 'virtual_parent')
|
|
||||||
|
|
||||||
def is_external_ports_supported(self):
|
def is_external_ports_supported(self):
|
||||||
return self._nb_idl.is_col_present(
|
return self._nb_idl.is_col_present(
|
||||||
'Logical_Switch_Port', 'ha_chassis_group')
|
'Logical_Switch_Port', 'ha_chassis_group')
|
||||||
@ -259,8 +254,7 @@ class OVNClient(object):
|
|||||||
subnet['cidr'].split('/')[1])
|
subnet['cidr'].split('/')[1])
|
||||||
|
|
||||||
# Check if the port being created is a virtual port
|
# Check if the port being created is a virtual port
|
||||||
if (self._is_virtual_port_supported() and
|
if not port['device_owner']:
|
||||||
not port['device_owner']):
|
|
||||||
parents = self.get_virtual_port_parents(ip_addr, port)
|
parents = self.get_virtual_port_parents(ip_addr, port)
|
||||||
if parents:
|
if parents:
|
||||||
port_type = ovn_const.LSP_TYPE_VIRTUAL
|
port_type = ovn_const.LSP_TYPE_VIRTUAL
|
||||||
@ -470,8 +464,7 @@ class OVNClient(object):
|
|||||||
# Check if the parent port was created with the
|
# Check if the parent port was created with the
|
||||||
# allowed_address_pairs already set
|
# allowed_address_pairs already set
|
||||||
allowed_address_pairs = port.get('allowed_address_pairs', [])
|
allowed_address_pairs = port.get('allowed_address_pairs', [])
|
||||||
if (self._is_virtual_port_supported() and
|
if (allowed_address_pairs and
|
||||||
allowed_address_pairs and
|
|
||||||
port_info.type != ovn_const.LSP_TYPE_VIRTUAL):
|
port_info.type != ovn_const.LSP_TYPE_VIRTUAL):
|
||||||
addrs = [addr['ip_address'] for addr in allowed_address_pairs]
|
addrs = [addr['ip_address'] for addr in allowed_address_pairs]
|
||||||
self._set_unset_virtual_port_type(context, txn, port, addrs)
|
self._set_unset_virtual_port_type(context, txn, port, addrs)
|
||||||
@ -595,8 +588,7 @@ class OVNClient(object):
|
|||||||
ovn_port = self._nb_idl.lookup('Logical_Switch_Port', port['id'])
|
ovn_port = self._nb_idl.lookup('Logical_Switch_Port', port['id'])
|
||||||
addr_pairs_diff = utils.compute_address_pairs_diff(ovn_port, port)
|
addr_pairs_diff = utils.compute_address_pairs_diff(ovn_port, port)
|
||||||
|
|
||||||
if (self._is_virtual_port_supported() and
|
if port_info.type != ovn_const.LSP_TYPE_VIRTUAL:
|
||||||
port_info.type != ovn_const.LSP_TYPE_VIRTUAL):
|
|
||||||
self._set_unset_virtual_port_type(
|
self._set_unset_virtual_port_type(
|
||||||
context, txn, port, addr_pairs_diff.added)
|
context, txn, port, addr_pairs_diff.added)
|
||||||
self._set_unset_virtual_port_type(
|
self._set_unset_virtual_port_type(
|
||||||
@ -683,8 +675,7 @@ class OVNClient(object):
|
|||||||
self.add_txns_to_remove_port_dns_records(txn, port_object)
|
self.add_txns_to_remove_port_dns_records(txn, port_object)
|
||||||
|
|
||||||
# Check if the port being deleted is a virtual parent
|
# Check if the port being deleted is a virtual parent
|
||||||
if (ovn_port.type != ovn_const.LSP_TYPE_VIRTUAL and
|
if ovn_port.type != ovn_const.LSP_TYPE_VIRTUAL:
|
||||||
self._is_virtual_port_supported()):
|
|
||||||
ls = self._nb_idl.ls_get(ovn_network_name).execute(
|
ls = self._nb_idl.ls_get(ovn_network_name).execute(
|
||||||
check_error=True)
|
check_error=True)
|
||||||
cmd = self._nb_idl.unset_lswitch_port_to_virtual_type
|
cmd = self._nb_idl.unset_lswitch_port_to_virtual_type
|
||||||
|
@ -207,9 +207,6 @@ class TestNetworkMTUUpdate(base.TestOVNFunctionalBase):
|
|||||||
second_revision.updated_at)
|
second_revision.updated_at)
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('neutron.plugins.ml2.drivers.ovn.mech_driver.'
|
|
||||||
'ovsdb.ovn_client.OVNClient._is_virtual_port_supported',
|
|
||||||
lambda *args: True)
|
|
||||||
class TestVirtualPorts(base.TestOVNFunctionalBase):
|
class TestVirtualPorts(base.TestOVNFunctionalBase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -62,6 +62,7 @@ from neutron.ipam.drivers.neutrondb_ipam import driver as ipam_driver
|
|||||||
from neutron.ipam import exceptions as ipam_exc
|
from neutron.ipam import exceptions as ipam_exc
|
||||||
from neutron.objects import network as network_obj
|
from neutron.objects import network as network_obj
|
||||||
from neutron.objects import router as l3_obj
|
from neutron.objects import router as l3_obj
|
||||||
|
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_client
|
||||||
from neutron import policy
|
from neutron import policy
|
||||||
from neutron import quota
|
from neutron import quota
|
||||||
from neutron.quota import resource_registry
|
from neutron.quota import resource_registry
|
||||||
@ -1009,6 +1010,13 @@ class TestV2HTTPResponse(NeutronDbPluginV2TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestPortsV2(NeutronDbPluginV2TestCase):
|
class TestPortsV2(NeutronDbPluginV2TestCase):
|
||||||
|
|
||||||
|
def setUp(self, **kwargs):
|
||||||
|
super().setUp(**kwargs)
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
def test_create_port_json(self):
|
def test_create_port_json(self):
|
||||||
keys = [('admin_state_up', True), ('status', self.port_create_status)]
|
keys = [('admin_state_up', True), ('status', self.port_create_status)]
|
||||||
with self.network(shared=True) as network:
|
with self.network(shared=True) as network:
|
||||||
|
@ -29,6 +29,7 @@ from neutron.db import db_base_plugin_v2
|
|||||||
from neutron.db import portsecurity_db
|
from neutron.db import portsecurity_db
|
||||||
from neutron.db import securitygroups_db
|
from neutron.db import securitygroups_db
|
||||||
from neutron.extensions import securitygroup as ext_sg
|
from neutron.extensions import securitygroup as ext_sg
|
||||||
|
from neutron.plugins.ml2.drivers.ovn.mech_driver.ovsdb import ovn_client
|
||||||
from neutron import quota
|
from neutron import quota
|
||||||
from neutron.tests.unit.db import test_db_base_plugin_v2
|
from neutron.tests.unit.db import test_db_base_plugin_v2
|
||||||
from neutron.tests.unit.extensions import test_securitygroup
|
from neutron.tests.unit.extensions import test_securitygroup
|
||||||
@ -186,6 +187,9 @@ class TestPortSecurity(PortSecurityDBTestCase):
|
|||||||
commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation')
|
commit_res = mock.patch.object(quota.QuotaEngine, 'commit_reservation')
|
||||||
self.mock_quota_make_res = make_res.start()
|
self.mock_quota_make_res = make_res.start()
|
||||||
self.mock_quota_commit_res = commit_res.start()
|
self.mock_quota_commit_res = commit_res.start()
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
def test_create_network_with_portsecurity_mac(self):
|
def test_create_network_with_portsecurity_mac(self):
|
||||||
res = self._create_network('json', 'net1', True)
|
res = self._create_network('json', 'net1', True)
|
||||||
|
@ -133,6 +133,9 @@ class TestOVNMechanismDriverBase(MechDriverSetupBase,
|
|||||||
p = mock.patch.object(ovn_revision_numbers_db, 'bump_revision')
|
p = mock.patch.object(ovn_revision_numbers_db, 'bump_revision')
|
||||||
p.start()
|
p.start()
|
||||||
self.addCleanup(p.stop)
|
self.addCleanup(p.stop)
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
def test_delete_mac_binding_entries(self):
|
def test_delete_mac_binding_entries(self):
|
||||||
self.config(group='ovn', ovn_sb_private_key=None)
|
self.config(group='ovn', ovn_sb_private_key=None)
|
||||||
@ -159,6 +162,13 @@ class TestOVNMechanismDriverBase(MechDriverSetupBase,
|
|||||||
|
|
||||||
|
|
||||||
class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
class TestOVNMechanismDriver(TestOVNMechanismDriverBase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
@mock.patch.object(ovsdb_monitor.OvnInitPGNbIdl, 'from_server')
|
@mock.patch.object(ovsdb_monitor.OvnInitPGNbIdl, 'from_server')
|
||||||
@mock.patch.object(ovsdb_monitor, 'short_living_ovsdb_api')
|
@mock.patch.object(ovsdb_monitor, 'short_living_ovsdb_api')
|
||||||
def test__create_neutron_pg_drop_non_existing(
|
def test__create_neutron_pg_drop_non_existing(
|
||||||
@ -2214,6 +2224,9 @@ class OVNMechanismDriverTestCase(MechDriverSetupBase,
|
|||||||
p = mock.patch.object(ovn_utils, 'get_revision_number', return_value=1)
|
p = mock.patch.object(ovn_utils, 'get_revision_number', return_value=1)
|
||||||
p.start()
|
p.start()
|
||||||
self.addCleanup(p.stop)
|
self.addCleanup(p.stop)
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
|
|
||||||
class TestOVNMechanismDriverBasicGet(test_plugin.TestMl2BasicGet,
|
class TestOVNMechanismDriverBasicGet(test_plugin.TestMl2BasicGet,
|
||||||
@ -3209,6 +3222,9 @@ class TestOVNMechanismDriverSecurityGroup(MechDriverSetupBase,
|
|||||||
super(TestOVNMechanismDriverSecurityGroup, self).setUp()
|
super(TestOVNMechanismDriverSecurityGroup, self).setUp()
|
||||||
self.ctx = context.get_admin_context()
|
self.ctx = context.get_admin_context()
|
||||||
revision_plugin.RevisionPlugin()
|
revision_plugin.RevisionPlugin()
|
||||||
|
self.mock_vp_parents = mock.patch.object(
|
||||||
|
ovn_client.OVNClient, 'get_virtual_port_parents',
|
||||||
|
return_value=None).start()
|
||||||
|
|
||||||
def _delete_default_sg_rules(self, security_group_id):
|
def _delete_default_sg_rules(self, security_group_id):
|
||||||
res = self._list(
|
res = self._list(
|
||||||
@ -3714,8 +3730,6 @@ class TestOVNVtepPortBinding(OVNMechanismDriverTestCase):
|
|||||||
ovn_port_info.options["vtep-logical-switch"])
|
ovn_port_info.options["vtep-logical-switch"])
|
||||||
|
|
||||||
|
|
||||||
@mock.patch.object(ovn_client.OVNClient, '_is_virtual_port_supported',
|
|
||||||
lambda *args: True)
|
|
||||||
class TestOVNVVirtualPort(OVNMechanismDriverTestCase):
|
class TestOVNVVirtualPort(OVNMechanismDriverTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Virtual ports are supported in OVN since version 2.12. Since Yoga, this
|
||||||
|
support is mandatory. The minimum OVN SB schema version must be 2.5.
|
Loading…
Reference in New Issue
Block a user