[OVN] Remove backwards compatibility with OVN < v20.09

This patch removes the compatibility with OVN under v20.09. That
implies the OVN Southbound definition has "Chassis_Private" table.
Any previous check is removed from the code.

This patch also adds a sanity check, testing that the OVN Southbound
database definition is greater or equal to 2.9.0 [1].

The testing OVN NB and SB schemas are updated to the files contained in
OVN v22.09. The new testing NB schema version is 6.3.9; the new testing
SB schema version is 20.25.0.

[1]4adc10f581

Closes-Bug: #2002839
Change-Id: Iec8854749a1df81eb6a7154d3f951e176c69156d
This commit is contained in:
Rodolfo Alonso Hernandez 2023-01-16 16:58:26 +01:00
parent 119c3ba85c
commit a579e504e9
16 changed files with 352 additions and 112 deletions

View File

@ -311,10 +311,8 @@ class SbGlobalUpdateEvent(row_event.RowEvent):
def run(self, event, row, old):
def _update_chassis(self, row):
table = ('Chassis_Private' if self.agent.has_chassis_private
else 'Chassis')
self.agent.sb_idl.db_set(
table, self.agent.chassis, ('external_ids', {
'Chassis_Private', self.agent.chassis, ('external_ids', {
ovn_const.OVN_AGENT_METADATA_SB_CFG_KEY:
str(row.nb_cfg)})).execute()
@ -384,27 +382,16 @@ class MetadataAgent(object):
self._load_config()
tables = ('Encap', 'Port_Binding', 'Datapath_Binding', 'SB_Global',
'Chassis')
'Chassis', 'Chassis_Private')
events = (PortBindingUpdatedEvent(self),
PortBindingDeletedEvent(self),
SbGlobalUpdateEvent(self),
ChassisPrivateCreateEvent(self),
)
# TODO(lucasagomes): Remove this in the future. Try to register
# the Chassis_Private table, if not present, fallback to the normal
# Chassis table.
# Open the connection to OVN SB database.
self.has_chassis_private = False
self._post_fork_event.clear()
try:
self.sb_idl = ovsdb.MetadataAgentOvnSbIdl(
chassis=self.chassis, tables=tables + ('Chassis_Private', ),
events=events + (ChassisPrivateCreateEvent(self), )).start()
self.has_chassis_private = True
except AssertionError:
self.sb_idl = ovsdb.MetadataAgentOvnSbIdl(
chassis=self.chassis, tables=tables,
events=events + (ChassisCreateEvent(self), )).start()
self.sb_idl = ovsdb.MetadataAgentOvnSbIdl(
chassis=self.chassis, tables=tables, events=events).start()
# Now IDL connections can be safely used.
self._post_fork_event.set()
@ -426,11 +413,10 @@ class MetadataAgent(object):
def register_metadata_agent(self):
# NOTE(lucasagomes): db_add() will not overwrite the UUID if
# it's already set.
table = ('Chassis_Private' if self.has_chassis_private else 'Chassis')
# Generate unique, but consistent metadata id for chassis name
agent_id = uuid.uuid5(self.chassis_id, 'metadata_agent')
ext_ids = {ovn_const.OVN_AGENT_METADATA_ID_KEY: str(agent_id)}
self.sb_idl.db_add(table, self.chassis, 'external_ids',
self.sb_idl.db_add('Chassis_Private', self.chassis, 'external_ids',
ext_ids).execute(check_error=True)
def _get_own_chassis_name(self):

View File

@ -64,6 +64,7 @@ OVN_NB_DB_SCHEMA_PORT_GROUP = '5.11.0'
OVN_NB_DB_SCHEMA_STATELESS_NAT = '5.17.0'
OVN_SB_DB_SCHEMA_VIRTUAL_PORT = '2.5.0'
OVN_LOCALNET_LEARN_FDB = '22.09.0'
OVN_SB_DB_SCHEMA_CHASSIS_PRIVATE = '2.9.0'
class OVNCheckType(enum.Enum):
@ -695,3 +696,17 @@ def ovn_localnet_learn_fdb_support():
'Exception: %s', e)
return False
return True
def ovn_sb_db_schema_chassis_private_supported():
try:
ver = _get_ovn_version(OVNCheckType.sb_db_schema)
minver = versionutils.convert_version_to_tuple(
OVN_SB_DB_SCHEMA_CHASSIS_PRIVATE)
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

View File

@ -353,6 +353,13 @@ def check_ovn_localnet_learn_fdb_support():
if not result:
LOG.warning('OVN does not support localnet_learn_fdb option. '
'This support was added in OVN 22.09.')
def check_ovn_sb_db_schema_chassis_private():
result = checks.ovn_sb_db_schema_chassis_private_supported()
if not result:
LOG.warning('OVN SB DB schema does not support chassis private. This '
'support was added in DB schema version 2.9.0.')
return result
@ -444,6 +451,10 @@ OPTS = [
check_ovn_localnet_learn_fdb_support,
help=_('Check OVN supports localnet_learn_fdb option'),
default=False),
BoolOptCallback('ovn_sb_db_schema_chassis_private_support',
check_ovn_sb_db_schema_chassis_private,
help=_('Check OVN SB DB schema supports Chassis_Private'),
default=False),
]

View File

@ -63,19 +63,22 @@ class NeutronAgent(abc.ABC):
self.set_down = False
@staticmethod
def chassis_from_private(chassis_private):
def _get_chassis(chassis_or_chassis_private):
"""Return the chassis register
The input could be the chassis register itself or the chassis private.
"""
try:
return chassis_private.chassis[0]
return chassis_or_chassis_private.chassis[0]
except AttributeError:
# No Chassis_Private support, just use Chassis
return chassis_private
return chassis_or_chassis_private
except IndexError:
# Chassis register has been deleted but not Chassis_Private.
return DeletedChassis
@property
def chassis(self):
return self.chassis_from_private(self.chassis_private)
return self._get_chassis(self.chassis_private)
def as_dict(self):
return {
@ -143,7 +146,7 @@ class ControllerAgent(NeutronAgent):
@staticmethod # it is by default, but this makes pep8 happy
def __new__(cls, chassis_private, driver):
_chassis = cls.chassis_from_private(chassis_private)
_chassis = cls._get_chassis(chassis_private)
other_config = ovn_utils.get_ovn_chassis_other_config(_chassis)
if 'enable-chassis-as-gw' in other_config.get('ovn-cms-options', []):
cls = ControllerGatewayAgent
@ -168,7 +171,7 @@ class ControllerAgent(NeutronAgent):
def update(self, chassis_private, clear_down=False):
super().update(chassis_private, clear_down)
_chassis = self.chassis_from_private(chassis_private)
_chassis = self._get_chassis(chassis_private)
other_config = ovn_utils.get_ovn_chassis_other_config(_chassis)
if 'enable-chassis-as-gw' in other_config.get('ovn-cms-options', []):
self.__class__ = ControllerGatewayAgent
@ -179,7 +182,7 @@ class ControllerGatewayAgent(ControllerAgent):
def update(self, chassis_private, clear_down=False):
super().update(chassis_private, clear_down)
_chassis = self.chassis_from_private(chassis_private)
_chassis = self._get_chassis(chassis_private)
other_config = ovn_utils.get_ovn_chassis_other_config(_chassis)
if ('enable-chassis-as-gw' not in
other_config.get('ovn-cms-options', [])):

View File

@ -138,10 +138,7 @@ class OVNMechanismDriver(api.MechanismDriver):
OVN_MIN_GENEVE_MAX_HEADER_SIZE)
raise SystemExit(1)
self._setup_vif_port_bindings()
if impl_idl_ovn.OvsdbSbOvnIdl.schema_has_table('Chassis_Private'):
self.agent_chassis_table = 'Chassis_Private'
else:
self.agent_chassis_table = 'Chassis'
self.agent_chassis_table = 'Chassis_Private'
self.subscribe()
self.qos_driver = qos_driver.OVNQosDriver.create(self)
self.trunk_driver = trunk_driver.OVNTrunkDriver.create(self)

View File

@ -367,8 +367,7 @@ class ChassisAgentTypeChangeEvent(ChassisEvent):
'external_ids')
if not getattr(old, other_config, False):
return False
chassis = n_agent.NeutronAgent.chassis_from_private(row)
new_other_config = utils.get_ovn_chassis_other_config(chassis)
new_other_config = utils.get_ovn_chassis_other_config(row)
old_other_config = utils.get_ovn_chassis_other_config(old)
agent_type_change = new_other_config.get('ovn-cms-options', []) != (
old_other_config.get('ovn-cms-options', []))
@ -670,6 +669,7 @@ class BaseOvnIdl(Ml2OvnIdlBase):
class BaseOvnSbIdl(Ml2OvnIdlBase):
@classmethod
def from_server(cls, connection_string, helper):
helper.register_table('Chassis_Private')
helper.register_table('Chassis')
helper.register_table('Encap')
helper.register_table('Port_Binding')
@ -725,13 +725,6 @@ class OvnIdlDistributedLock(BaseOvnIdl):
self.update_tables(tables, row.schema[0])
if self.driver.agent_chassis_table == 'Chassis_Private':
if 'Chassis_Private' not in self.tables:
self.driver.agent_chassis_table = 'Chassis'
else:
if 'Chassis_Private' in self.tables:
self.driver.agent_chassis_table = 'Chassis_Private'
def notify(self, event, row, updates=None):
try:
self.handle_db_schema_changes(event, row)
@ -828,10 +821,9 @@ class OvnSbIdl(OvnIdlDistributedLock):
@classmethod
def from_server(cls, connection_string, helper, driver):
if 'Chassis_Private' in helper.schema_json['tables']:
helper.register_table('Chassis_Private')
if 'FDB' in helper.schema_json['tables']:
helper.register_table('FDB')
helper.register_table('Chassis_Private')
helper.register_table('Chassis')
helper.register_table('Encap')
helper.register_table('Port_Binding')

View File

@ -92,9 +92,7 @@ class TestMetadataAgent(base.TestOVNFunctionalBase):
@property
def agent_chassis_table(self):
if self.agent.has_chassis_private:
return 'Chassis_Private'
return 'Chassis'
return 'Chassis_Private'
def _start_metadata_agent(self):
conf = self.useFixture(fixture_config.Config()).conf

View File

@ -433,17 +433,15 @@ class TestOVNFunctionalBase(test_plugin.Ml2PluginV2TestCase,
name, ['geneve'], '172.24.4.%d' % self._counter,
external_ids=external_ids, hostname=host,
other_config=other_config).execute(check_error=True)
if self.sb_api.is_table_present('Chassis_Private'):
nb_cfg_timestamp = timeutils.utcnow_ts() * 1000
self.sb_api.db_create(
'Chassis_Private', name=name, external_ids=external_ids,
chassis=chassis.uuid, nb_cfg_timestamp=nb_cfg_timestamp
).execute(check_error=True)
nb_cfg_timestamp = timeutils.utcnow_ts() * 1000
self.sb_api.db_create(
'Chassis_Private', name=name, external_ids=external_ids,
chassis=chassis.uuid, nb_cfg_timestamp=nb_cfg_timestamp
).execute(check_error=True)
return name
def del_fake_chassis(self, chassis, if_exists=True):
self.sb_api.chassis_del(
chassis, if_exists=if_exists).execute(check_error=True)
if self.sb_api.is_table_present('Chassis_Private'):
self.sb_api.db_destroy(
'Chassis_Private', chassis).execute(check_error=True)
self.sb_api.db_destroy(
'Chassis_Private', chassis).execute(check_error=True)

View File

@ -524,8 +524,6 @@ class TestAgentMonitor(base.TestOVNFunctionalBase):
int(chassis_ts / 1000), datetime.timezone.utc)
return agent.updated_at == updated_at
if not self.sb_api.is_table_present('Chassis_Private'):
self.skipTest('Ovn sb not support Chassis_Private')
timestamp = timeutils.utcnow_ts()
nb_cfg_timestamp = timestamp * 1000
self.sb_api.db_set('Chassis_Private', self.chassis_name, (
@ -558,9 +556,6 @@ class TestAgentMonitor(base.TestOVNFunctionalBase):
agent = neutron_agent.AgentCache().get(self.chassis_name)
return agent.updated_at != 0
if not self.sb_api.is_table_present('Chassis_Private'):
self.skipTest('Ovn sb not support Chassis_Private')
# Set nb_cfg to some realistic value, so that the alive check can
# actually work
self.nb_api.db_set(

View File

@ -1196,15 +1196,11 @@ class TestAgentApi(base.TestOVNFunctionalBase):
agent_id = self.agent_types[ovn_const.OVN_CONTROLLER_AGENT]
agent = self.plugin.get_agent(self.context, agent_id)
heartbeat_timestamp = agent['heartbeat_timestamp']
if self.sb_api.is_table_present('Chassis_Private'):
chassis_ts = self.sb_api.db_get(
'Chassis_Private', self.chassis, 'nb_cfg_timestamp'
).execute(check_error=True)
updated_at = datetime.datetime.fromtimestamp(
int(chassis_ts / 1000))
# if table Chassis_Private present, agent.updated_at is
# Chassis_Private.nb_cfg_timestamp
self.assertEqual(updated_at, heartbeat_timestamp)
chassis_ts = self.sb_api.db_get(
'Chassis_Private', self.chassis, 'nb_cfg_timestamp'
).execute(check_error=True)
updated_at = datetime.datetime.fromtimestamp(int(chassis_ts / 1000))
self.assertEqual(updated_at, heartbeat_timestamp)
time.sleep(1)
# if chassis is not updated, agent's heartbeat_timestamp shouldn't
# be updated.

View File

@ -16,6 +16,7 @@ import datetime
from unittest import mock
import eventlet
from oslo_utils import timeutils
from neutron.common.ovn import constants as ovn_const
from neutron.plugins.ml2.drivers.ovn.agent import neutron_agent
@ -31,8 +32,13 @@ class AgentCacheTestCase(base.BaseTestCase):
self.addCleanup(self._clean_agent_cache)
self.names_ref = []
for i in range(10): # Add 10 agents.
chassis = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={'other_config': {}})
chassis_private = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={'name': 'chassis' + str(i), 'other_config': {}})
attrs={'name': 'chassis' + str(i),
'other_config': {},
'chassis': [chassis],
'nb_cfg_timestamp': timeutils.utcnow_ts() * 1000})
self.agent_cache.update(ovn_const.OVN_CONTROLLER_AGENT,
chassis_private)
self.names_ref.append('chassis' + str(i))
@ -49,8 +55,12 @@ class AgentCacheTestCase(base.BaseTestCase):
def _add_and_delete_agents(self):
self.agent_cache.delete('chassis8')
chassis = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={'other_config': {}})
chassis_private = fakes.FakeOvsdbRow.create_one_ovsdb_row(
attrs={'name': 'chassis10'})
attrs={'name': 'chassis10',
'chassis': [chassis],
'nb_cfg_timestamp': timeutils.utcnow_ts() * 1000})
self.agent_cache.update(ovn_const.OVN_CONTROLLER_AGENT,
chassis_private)

View File

@ -1,14 +1,17 @@
{
"name": "OVN_Northbound",
"version": "5.23.0",
"cksum": "111023208 25806",
"version": "6.3.0",
"cksum": "4042813038 31869",
"tables": {
"NB_Global": {
"columns": {
"name": {"type": "string"},
"nb_cfg": {"type": {"key": "integer"}},
"nb_cfg_timestamp": {"type": {"key": "integer"}},
"sb_cfg": {"type": {"key": "integer"}},
"sb_cfg_timestamp": {"type": {"key": "integer"}},
"hv_cfg": {"type": {"key": "integer"}},
"hv_cfg_timestamp": {"type": {"key": "integer"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
@ -27,6 +30,19 @@
"ipsec": {"type": "boolean"}},
"maxRows": 1,
"isRoot": true},
"Copp": {
"columns": {
"name": {"type": "string"},
"meters": {
"type": {"key": "string",
"value": "string",
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Logical_Switch": {
"columns": {
"name": {"type": "string"},
@ -50,11 +66,19 @@
"refType": "weak"},
"min": 0,
"max": "unlimited"}},
"load_balancer_group": {
"type": {"key": {"type": "uuid",
"refTable": "Load_Balancer_Group"},
"min": 0,
"max": "unlimited"}},
"dns_records": {"type": {"key": {"type": "uuid",
"refTable": "DNS",
"refType": "weak"},
"min": 0,
"max": "unlimited"}},
"copp": {"type": {"key": {"type": "uuid", "refTable": "Copp",
"refType": "weak"},
"min": 0, "max": 1}},
"other_config": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
@ -185,10 +209,25 @@
["eth_src", "eth_dst", "ip_src", "ip_dst",
"tp_src", "tp_dst"]]},
"min": 0, "max": "unlimited"}},
"options": {
"type": {"key": "string",
"value": "string",
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": true},
"Load_Balancer_Group": {
"columns": {
"name": {"type": "string"},
"load_balancer": {"type": {"key": {"type": "uuid",
"refTable": "Load_Balancer",
"refType": "weak"},
"min": 0,
"max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true},
"Load_Balancer_Health_Check": {
"columns": {
"vip": {"type": "string"},
@ -213,7 +252,10 @@
"enum": ["set", ["from-lport", "to-lport"]]}}},
"match": {"type": "string"},
"action": {"type": {"key": {"type": "string",
"enum": ["set", ["allow", "allow-related", "drop", "reject"]]}}},
"enum": ["set",
["allow", "allow-related",
"allow-stateless", "drop",
"reject"]]}}},
"log": {"type": "boolean"},
"severity": {"type": {"key": {"type": "string",
"enum": ["set",
@ -222,6 +264,14 @@
"debug"]]},
"min": 0, "max": 1}},
"meter": {"type": {"key": "string", "min": 0, "max": 1}},
"label": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 4294967295}}},
"options": {
"type": {"key": "string",
"value": "string",
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@ -261,6 +311,7 @@
"refType": "strong"},
"min": 1,
"max": "unlimited"}},
"fair": {"type": {"key": "boolean", "min": 0, "max": 1}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@ -310,6 +361,14 @@
"refType": "weak"},
"min": 0,
"max": "unlimited"}},
"load_balancer_group": {
"type": {"key": {"type": "uuid",
"refTable": "Load_Balancer_Group"},
"min": 0,
"max": "unlimited"}},
"copp": {"type": {"key": {"type": "uuid", "refTable": "Copp",
"refType": "weak"},
"min": 0, "max": 1}},
"options": {
"type": {"key": "string",
"value": "string",
@ -358,6 +417,7 @@
"isRoot": false},
"Logical_Router_Static_Route": {
"columns": {
"route_table": {"type": "string"},
"ip_prefix": {"type": "string"},
"policy": {"type": {"key": {"type": "string",
"enum": ["set", ["src-ip",
@ -365,6 +425,13 @@
"min": 0, "max": 1}},
"nexthop": {"type": "string"},
"output_port": {"type": {"key": "string", "min": 0, "max": 1}},
"bfd": {"type": {"key": {"type": "uuid", "refTable": "BFD",
"refType": "weak"},
"min": 0,
"max": 1}},
"options": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@ -379,6 +446,11 @@
"key": {"type": "string",
"enum": ["set", ["allow", "drop", "reroute"]]}}},
"nexthop": {"type": {"key": "string", "min": 0, "max": 1}},
"nexthops": {"type": {
"key": "string", "min": 0, "max": "unlimited"}},
"options": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@ -397,6 +469,22 @@
"snat",
"dnat_and_snat"
]]}}},
"allowed_ext_ips": {"type": {
"key": {"type": "uuid", "refTable": "Address_Set",
"refType": "strong"},
"min": 0,
"max": 1}},
"exempted_ext_ips": {"type": {
"key": {"type": "uuid", "refTable": "Address_Set",
"refType": "strong"},
"min": 0,
"max": 1}},
"gateway_port": {
"type": {"key": {"type": "uuid",
"refTable": "Logical_Router_Port",
"refType": "weak"},
"min": 0,
"max": 1}},
"options": {"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"external_ids": {
@ -499,5 +587,39 @@
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["name"]],
"isRoot": true}}
"isRoot": true},
"BFD": {
"columns": {
"logical_port": {"type": "string"},
"dst_ip": {"type": "string"},
"min_tx": {"type": {"key": {"type": "integer",
"minInteger": 1},
"min": 0, "max": 1}},
"min_rx": {"type": {"key": {"type": "integer"},
"min": 0, "max": 1}},
"detect_mult": {"type": {"key": {"type": "integer",
"minInteger": 1},
"min": 0, "max": 1}},
"status": {
"type": {"key": {"type": "string",
"enum": ["set", ["down", "init", "up",
"admin_down"]]},
"min": 0, "max": 1}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"options": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["logical_port", "dst_ip"]],
"isRoot": true},
"Static_MAC_Binding": {
"columns": {
"logical_port": {"type": "string"},
"ip": {"type": "string"},
"mac": {"type": "string"},
"override_dynamic_mac": {"type": "boolean"}},
"indexes": [["logical_port", "ip"]],
"isRoot": true}
}
}

View File

@ -1,7 +1,7 @@
{
"name": "OVN_Southbound",
"version": "2.7.0",
"cksum": "4286723485 21693",
"version": "20.25.0",
"cksum": "53184112 28845",
"tables": {
"SB_Global": {
"columns": {
@ -38,11 +38,28 @@
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"other_config": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"transport_zones" : {"type": {"key": "string",
"min": 0,
"max": "unlimited"}}},
"isRoot": true,
"indexes": [["name"]]},
"Chassis_Private": {
"columns": {
"name": {"type": "string"},
"chassis": {"type": {"key": {"type": "uuid",
"refTable": "Chassis",
"refType": "weak"},
"min": 0, "max": 1}},
"nb_cfg": {"type": {"key": "integer"}},
"nb_cfg_timestamp": {"type": {"key": "integer"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": true,
"indexes": [["name"]]},
"Encap": {
"columns": {
"type": {"type": {"key": {
@ -73,23 +90,42 @@
"isRoot": true},
"Logical_Flow": {
"columns": {
"logical_datapath": {"type": {"key": {"type": "uuid",
"refTable": "Datapath_Binding"}}},
"logical_datapath":
{"type": {"key": {"type": "uuid",
"refTable": "Datapath_Binding"},
"min": 0, "max": 1}},
"logical_dp_group":
{"type": {"key": {"type": "uuid",
"refTable": "Logical_DP_Group"},
"min": 0, "max": 1}},
"pipeline": {"type": {"key": {"type": "string",
"enum": ["set", ["ingress",
"egress"]]}}},
"table_id": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 23}}},
"maxInteger": 32}}},
"priority": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 65535}}},
"match": {"type": "string"},
"actions": {"type": "string"},
"tags": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"controller_meter": {"type": {"key": {"type": "string"},
"min": 0, "max": 1}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": true},
"Logical_DP_Group": {
"columns": {
"datapaths":
{"type": {"key": {"type": "uuid",
"refTable": "Datapath_Binding",
"refType": "weak"},
"min": 0, "max": "unlimited"}}},
"isRoot": false},
"Multicast_Group": {
"columns": {
"datapath": {"type": {"key": {"type": "uuid",
@ -102,7 +138,7 @@
"ports": {"type": {"key": {"type": "uuid",
"refTable": "Port_Binding",
"refType": "weak"},
"min": 1, "max": "unlimited"}}},
"min": 0, "max": "unlimited"}}},
"indexes": [["datapath", "tunnel_key"],
["datapath", "name"]],
"isRoot": true},
@ -135,6 +171,9 @@
"type": {"key": {"type": "integer",
"minInteger": 1,
"maxInteger": 16777215}}},
"load_balancers": {"type": {"key": {"type": "uuid"},
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
@ -179,20 +218,41 @@
"refTable": "Chassis",
"refType": "weak"},
"min": 0, "max": 1}},
"additional_chassis": {"type": {"key": {"type": "uuid",
"refTable": "Chassis",
"refType": "weak"},
"min": 0, "max": "unlimited"}},
"encap": {"type": {"key": {"type": "uuid",
"refTable": "Encap",
"refType": "weak"},
"min": 0, "max": 1}},
"additional_encap": {"type": {"key": {"type": "uuid",
"refTable": "Encap",
"refType": "weak"},
"min": 0, "max": "unlimited"}},
"mac": {"type": {"key": "string",
"min": 0,
"max": "unlimited"}},
"port_security": {"type": {"key": "string",
"min": 0,
"max": "unlimited"}},
"nat_addresses": {"type": {"key": "string",
"min": 0,
"max": "unlimited"}},
"up": {"type": {"key": "boolean", "min": 0, "max": 1}},
"external_ids": {"type": {"key": "string",
"value": "string",
"min": 0,
"max": "unlimited"}}},
"max": "unlimited"}},
"requested_chassis": {"type": {"key": {"type": "uuid",
"refTable": "Chassis",
"refType": "weak"},
"min": 0, "max": 1}},
"requested_additional_chassis": {
"type": {"key": {"type": "uuid",
"refTable": "Chassis",
"refType": "weak"},
"min": 0, "max": "unlimited"}}},
"indexes": [["datapath", "tunnel_key"], ["logical_port"]],
"isRoot": true},
"MAC_Binding": {
@ -200,6 +260,7 @@
"logical_port": {"type": "string"},
"ip": {"type": "string"},
"mac": {"type": "string"},
"timestamp": {"type": {"key": "integer"}},
"datapath": {"type": {"key": {"type": "uuid",
"refTable": "Datapath_Binding"}}}},
"indexes": [["logical_port", "ip"]],
@ -214,7 +275,8 @@
"type": {"key": {
"type": "string",
"enum": ["set", ["bool", "uint8", "uint16", "uint32",
"ipv4", "static_routes", "str"]]}}}},
"ipv4", "static_routes", "str",
"host_id", "domains"]]}}}},
"isRoot": true},
"DHCPv6_Options": {
"columns": {
@ -414,7 +476,7 @@
"min": 0, "max": 1}},
"port": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 32767}}},
"maxInteger": 65535}}},
"logical_port": {"type": "string"},
"src_mac": {"type": "string"},
"src_ip": {"type": "string"},
@ -429,6 +491,80 @@
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["logical_port", "ip", "port", "protocol"]],
"isRoot": true},
"Load_Balancer": {
"columns": {
"name": {"type": "string"},
"vips": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"protocol": {
"type": {"key": {"type": "string",
"enum": ["set", ["tcp", "udp", "sctp"]]},
"min": 0, "max": 1}},
"datapaths": {
"type": {"key": {"type": "uuid",
"refTable": "Datapath_Binding"},
"min": 0, "max": "unlimited"}},
"datapath_group":
{"type": {"key": {"type": "uuid",
"refTable": "Logical_DP_Group"},
"min": 0, "max": 1}},
"options": {
"type": {"key": "string",
"value": "string",
"min": 0,
"max": "unlimited"}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": true},
"BFD": {
"columns": {
"src_port": {"type": {"key": {"type": "integer",
"minInteger": 49152,
"maxInteger": 65535}}},
"disc": {"type": {"key": {"type": "integer"}}},
"logical_port": {"type": "string"},
"dst_ip": {"type": "string"},
"min_tx": {"type": {"key": {"type": "integer"}}},
"min_rx": {"type": {"key": {"type": "integer"}}},
"detect_mult": {"type": {"key": {"type": "integer"}}},
"status": {
"type": {"key": {"type": "string",
"enum": ["set", ["down", "init", "up",
"admin_down"]]}}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}},
"options": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"indexes": [["logical_port", "dst_ip", "src_port", "disc"]],
"isRoot": true},
"FDB": {
"columns": {
"mac": {"type": "string"},
"dp_key": {
"type": {"key": {"type": "integer",
"minInteger": 1,
"maxInteger": 16777215}}},
"port_key": {
"type": {"key": {"type": "integer",
"minInteger": 1,
"maxInteger": 16777215}}}},
"indexes": [["mac", "dp_key"]],
"isRoot": true},
"Static_MAC_Binding": {
"columns": {
"logical_port": {"type": "string"},
"ip": {"type": "string"},
"mac": {"type": "string"},
"override_dynamic_mac": {"type": "boolean"},
"datapath": {"type": {
"key": {"type": "uuid",
"refTable": "Datapath_Binding"}}}},
"indexes": [["logical_port", "ip"]],
"isRoot": true}
}
}

View File

@ -304,45 +304,20 @@ class TestOvnIdlDistributedLock(base.BaseTestCase):
self.assertFalse(self.mock_update_tables.called)
def _test_handle_db_schema(self, agent_table, chassis_private_present):
def _test_handle_db_schema(self, agent_table):
database_table_row = self._create_fake_row('Database')
self.idl._tables_to_register[database_table_row.name] = 'foo'
self.fake_driver.agent_chassis_table = agent_table
if chassis_private_present:
self.idl.tables['Chassis_Private'] = 'foo'
else:
try:
del self.idl.tables['Chassis_Private']
except KeyError:
pass
self.idl.tables['Chassis_Private'] = 'foo'
self.idl.handle_db_schema_changes(
ovsdb_monitor.BaseEvent.ROW_CREATE, database_table_row)
def test_handle_db_schema_changes_old_schema_to_old_schema(self):
"""Agents use Chassis and should keep using Chassis table"""
self._test_handle_db_schema('Chassis', chassis_private_present=False)
self.assertEqual('Chassis', self.fake_driver.agent_chassis_table)
def test_handle_db_schema_changes_old_schema_to_new_schema(self):
"""Agents use Chassis and should start using Chassis_Private table"""
self._test_handle_db_schema('Chassis', chassis_private_present=True)
self.assertEqual('Chassis_Private',
self.fake_driver.agent_chassis_table)
def test_handle_db_schema_changes_new_schema_to_old_schema(self):
"""Agents use Chassis_Private and should start using Chassis table"""
self._test_handle_db_schema('Chassis_Private',
chassis_private_present=False)
self.assertEqual('Chassis', self.fake_driver.agent_chassis_table)
def test_handle_db_schema_changes_new_schema_to_new_schema(self):
"""Agents use Chassis_Private and should keep using Chassis_Private
table.
"""
self._test_handle_db_schema('Chassis_Private',
chassis_private_present=True)
self._test_handle_db_schema('Chassis_Private')
self.assertEqual('Chassis_Private',
self.fake_driver.agent_chassis_table)

View File

@ -105,6 +105,7 @@ class MechDriverSetupBase(abc.ABC):
chassis_private.nb_cfg = nb_cfg
chassis_private.uuid = uuid.uuid4()
chassis_private.name = name if name else str(uuid.uuid4())
chassis_private.nb_cfg_timestamp = timeutils.utcnow_ts() * 1000
return chassis_private
def _add_chassis_agent(self, nb_cfg, agent_type, chassis_private=None):

View File

@ -0,0 +1,5 @@
---
features:
- |
Removed support for OVN versions under 20.09. The "Chassis_Private" OVN
Southbound table is expected in the database definition.